public override Job JobOnThing(Pawn pawn, Thing t)
        {
            Vehicle_Cart cart = t as Vehicle_Cart;

            if (cart == null)
            {
                return((Job)null);
            }
            if (cart.IsForbidden(pawn.Faction) || !ReservationUtility.CanReserveAndReach(pawn, cart, PathEndMode.ClosestTouch, DangerUtility.NormalMaxDanger(pawn)))
            {
                return((Job)null);
            }
            if (FireUtility.IsBurning(cart))
            {
                JobFailReason.Is(ToolsForHaulUtility.BurningLowerTrans);
                return((Job)null);
            }
            if (ListerHaulables.ThingsPotentiallyNeedingHauling().Count == 0 && cart.storage.Count == 0)
            {
                JobFailReason.Is(ToolsForHaulUtility.NoHaulable);
                return((Job)null);
            }
            if (Find.SlotGroupManager.AllGroupsListInPriorityOrder.Count == 0)
            {
                JobFailReason.Is(ToolsForHaulUtility.NoEmptyPlaceLowerTrans);
                return((Job)null);
            }
            if (ToolsForHaulUtility.AvailableAnimalCart(cart) || ToolsForHaulUtility.AvailableCart(cart, pawn))
            {
                return(ToolsForHaulUtility.HaulWithTools(pawn, cart));
            }
            JobFailReason.Is(ToolsForHaulUtility.NoAvailableCart);
            return((Job)null);
        }
        public static Toil CheckDuplicates(Toil jumpToil, TargetIndex CarrierInd, TargetIndex HaulableInd)
        {
            Toil toil = new Toil();

            toil.initAction = () =>
            {
                IntVec3 storeCell = IntVec3.Invalid;
                Pawn    actor     = toil.GetActor();

                TargetInfo target = toil.actor.jobs.curJob.GetTarget(HaulableInd);
                if (target.Thing.def.stackLimit <= 1)
                {
                    return;
                }
                List <TargetInfo> targetQueue = toil.actor.jobs.curJob.GetTargetQueue(HaulableInd);
                if (!targetQueue.NullOrEmpty() && target.Thing.def.defName == targetQueue.First().Thing.def.defName)
                {
                    toil.actor.jobs.curJob.SetTarget(HaulableInd, targetQueue.First());
                    Find.Reservations.Reserve(actor, targetQueue.First());
                    targetQueue.RemoveAt(0);
                    toil.actor.jobs.curDriver.JumpToToil(jumpToil);
                    return;
                }
                Vehicle_Cart     cart     = toil.actor.jobs.curJob.GetTarget(CarrierInd).Thing as Vehicle_Cart;
                Apparel_Backpack backpack = toil.actor.jobs.curJob.GetTarget(CarrierInd).Thing as Apparel_Backpack;

                if (cart == null && backpack == null)
                {
                    Log.Error(actor.LabelCap + " Report: Don't have Carrier");
                    toil.actor.jobs.curDriver.EndJobWith(JobCondition.Errored);
                    return;
                }
                int curItemCount = (cart != null ? cart.storage.Count : backpack.slotsComp.slots.Count) + targetQueue.Count;
                int curItemStack = (cart != null ? cart.storage.TotalStackCount : backpack.slotsComp.slots.TotalStackCount)
                                   + targetQueue.Sum(item => item.Thing.stackCount);
                int maxItem  = cart != null ? cart.MaxItem : backpack.MaxItem;
                int maxStack = cart != null ? cart.MaxStack : backpack.MaxStack;
                if (curItemCount >= maxItem || curItemStack >= maxStack)
                {
                    return;
                }
                //Check target's nearby
                Thing thing = GenClosest.ClosestThing_Global_Reachable(actor.Position,
                                                                       ListerHaulables.ThingsPotentiallyNeedingHauling(),
                                                                       PathEndMode.Touch,
                                                                       TraverseParms.For(actor, Danger.Some),
                                                                       NearbyCell,
                                                                       item => !targetQueue.Contains(item) &&
                                                                       item.def.defName == target.Thing.def.defName &&
                                                                       !item.IsBurning() &&
                                                                       Find.Reservations.CanReserve(actor, item));
                if (thing != null)
                {
                    toil.actor.jobs.curJob.SetTarget(HaulableInd, thing);
                    Find.Reservations.Reserve(actor, thing);
                    toil.actor.jobs.curDriver.JumpToToil(jumpToil);
                }
            };
            return(toil);
        }
 public override bool ShouldSkip(Pawn pawn)
 {
     // Ticker for checking special hauling cases of filling stacks in containers from stockpiles
     CFS_ListerHaulables.ListerHaulablesTick();
     FindHaulablesInsideContainers();
     // Skip if no haulables in any list (ListerHaulables.ThingsPotentiallyNeedingHauling() will still count things inside container as hauling required, but they won't be hauled because of future checks)
     return(ListerHaulables.ThingsPotentiallyNeedingHauling().Count == 0 && haulables_blockedInListerHaulables.Count == 0 && haulables_insideContainers.Count == 0 && CFS_ListerHaulables.haulables.Count == 0);
 }
 public override IEnumerable <Thing> PotentialWorkThingsGlobal(Pawn pawn)
 {
     /* Required, because ListerHaulables removes things from haulables list, which are not fit in SlotGroups (can't stack things).
      * So i preserve the original list before it's changed after the first item is hauled to the destination point.
      */
     if (ListerHaulables.ThingsPotentiallyNeedingHauling().Count >= haulables_blockedInListerHaulables.Count)
     {
         haulables_blockedInListerHaulables = new List <Thing>(ListerHaulables.ThingsPotentiallyNeedingHauling());
     }
     // Merge all the required lists of haulables (original, blocked, inside containers and which are not counted at all, if containers already partially full (CFS_ListerHaulables.haulables), to fill the incomplete stacks)
     return(ListerHaulables.ThingsPotentiallyNeedingHauling().Union(haulables_blockedInListerHaulables).Union(haulables_insideContainers).Union(CFS_ListerHaulables.haulables).ToList());
 }
        public override IEnumerable <Thing> PotentialWorkThingsGlobal(Pawn pawn)
        {
            List <Thing>     list     = new List <Thing>();
            Apparel_Backpack backpack = ToolsForHaulUtility.TryGetBackpack(pawn);

            foreach (Thing thing in ListerHaulables.ThingsPotentiallyNeedingHauling())
            {
                if (thing.def.thingCategories.Exists(category => backpack.slotsComp.Properties.allowedThingCategoryDefs.Exists(subCategory => subCategory.ThisAndChildCategoryDefs.Contains(category)) && !backpack.slotsComp.Properties.forbiddenSubThingCategoryDefs.Exists(subCategory => subCategory.ThisAndChildCategoryDefs.Contains(category))))
                {
                    list.Add(thing);
                }
                //return ToolsForHaulUtility.Cart();
            }
            return(list);
        }
        public override bool ShouldSkip(Pawn pawn)
        {
            Trace.DebugWriteHaulingPawn(pawn);
            //Don't have haulables.
            if (ListerHaulables.ThingsPotentiallyNeedingHauling().Count == 0)
            {
                return(true);
            }

            //Should skip pawn that don't have backpack.
            if (ToolsForHaulUtility.TryGetBackpack(pawn) == null)
            {
                return(true);
            }
            return(false);
        }
        public static Job HaulWithTools(Pawn pawn, Vehicle_Cart cart = null)
        {
            Trace.stopWatchStart();

            //Job Setting
            JobDef              jobDef;
            TargetInfo          targetC;
            int                 maxItem;
            int                 thresholdItem;
            int                 reservedMaxItem;
            IEnumerable <Thing> remainingItems;
            bool                ShouldDrop;
            Thing               lastItem = ToolsForHaulUtility.TryGetBackpackLastItem(pawn);

            if (cart == null)
            {
                Apparel_Backpack backpack = ToolsForHaulUtility.TryGetBackpack(pawn);
                jobDef          = jobDefHaulWithBackpack;
                targetC         = backpack;
                maxItem         = backpack.MaxItem;
                thresholdItem   = (int)Math.Ceiling(maxItem * 0.5);
                reservedMaxItem = pawn.inventory.container.Count;
                remainingItems  = pawn.inventory.container;
                ShouldDrop      = true;
                if (lastItem != null)
                {
                    for (int i = 0; i < pawn.inventory.container.Count; i++)
                    {
                        if (pawn.inventory.container[i] == lastItem && (reservedMaxItem - (i + 1)) <= 0)
                        {
                            ShouldDrop = false;
                            break;
                        }
                    }
                }
            }
            else
            {
                jobDef = (cart.TryGetComp <CompMountable>().IsMounted&& cart.TryGetComp <CompMountable>().Driver.RaceProps.Animal)?
                         jobDefHaulWithAnimalCart : jobDefHaulWithCart;
                targetC         = cart;
                maxItem         = cart.MaxItem;
                thresholdItem   = (int)Math.Ceiling(maxItem * 0.5);
                reservedMaxItem = cart.storage.Count;
                remainingItems  = cart.storage;
                ShouldDrop      = (reservedMaxItem > 0) ? true : false;
            }
            Job job = new Job(jobDef);

            job.targetQueueA = new List <TargetInfo>();
            job.targetQueueB = new List <TargetInfo>();
            job.targetC      = targetC;

            Trace.AppendLine(pawn.LabelCap + " In HaulWithTools: " + jobDef.defName + "\n"
                             + "MaxItem: " + maxItem + " reservedMaxItem: " + reservedMaxItem);

            //Drop remaining item
            if (ShouldDrop)
            {
                Trace.AppendLine("Start Drop remaining item");
                bool startDrop = false;
                for (int i = 0; i < remainingItems.Count(); i++)
                {
                    if (cart == null && startDrop == false)
                    {
                        if (remainingItems.ElementAt(i) == lastItem)
                        {
                            startDrop = true;
                        }
                        else
                        {
                            continue;
                        }
                    }
                    IntVec3 storageCell = FindStorageCell(pawn, remainingItems.ElementAt(i), job.targetQueueB);
                    if (storageCell == IntVec3.Invalid)
                    {
                        break;
                    }
                    job.targetQueueB.Add(storageCell);
                }
                if (!job.targetQueueB.NullOrEmpty())
                {
                    Trace.AppendLine("Droping Job is issued");
                    Trace.LogMessage();
                    return(job);
                }
                if (cart != null && job.def == jobDefHaulWithCart && !cart.IsInValidStorage())
                {
                    Trace.AppendLine("In DismountInBase");
                    return(DismountInBase(pawn, cart));
                }
                JobFailReason.Is(ToolsForHaulUtility.NoEmptyPlaceLowerTrans);
                Trace.AppendLine("End Drop remaining item");
                Trace.AppendLine("No Job. Reason: " + JobFailReason.Reason);
                Trace.LogMessage();
                return((Job)null);
            }

            //Collect item
            Trace.AppendLine("Start Collect item");
            IntVec3 searchPos = (cart != null) ? cart.Position : pawn.Position;
            bool    flag1     = false;

            foreach (SlotGroup slotGroup in Find.SlotGroupManager.AllGroupsListInPriorityOrder)
            {
                Trace.AppendLine("Start searching slotGroup");
                if (slotGroup.CellsList.Count() - slotGroup.HeldThings.Count() < maxItem)
                {
                    continue;
                }

                //Counting valid items
                Trace.AppendLine("Start Counting valid items");
                int thingsCount = ListerHaulables.ThingsPotentiallyNeedingHauling().Count(item => slotGroup.Settings.AllowedToAccept(item));

                //Finding valid items
                Trace.AppendLine("Start Finding valid items");
                if (thingsCount > thresholdItem)
                {
                    //ClosestThing_Global_Reachable Configuration
                    Predicate <Thing> predicate = item
                                                  => !job.targetQueueA.Contains(item) && !FireUtility.IsBurning(item) &&
                                                  ((cart != null && cart.allowances.Allows(item)) || cart == null) &&
                                                  slotGroup.Settings.AllowedToAccept(item) &&
                                                  pawn.CanReserveAndReach(item, PathEndMode.Touch, DangerUtility.NormalMaxDanger(pawn));
                    //&& !(item is UnfinishedThing && ((UnfinishedThing)item).BoundBill != null)
                    //&& (item.def.IsNutritionSource && !SocialProperness.IsSociallyProper(item, pawn, false, false));
                    Thing thing = GenClosest.ClosestThing_Global_Reachable(searchPos,
                                                                           ListerHaulables.ThingsPotentiallyNeedingHauling(),
                                                                           PathEndMode.ClosestTouch,
                                                                           TraverseParms.For(TraverseMode.ByPawn, DangerUtility.NormalMaxDanger(pawn)),
                                                                           9999,
                                                                           predicate);
                    if (thing == null)
                    {
                        continue;
                    }
                    IntVec3 center = thing.Position;

                    //Enqueue items in valid distance
                    Trace.AppendLine("Start Enqueuing items in valid distance");
                    foreach (Thing item in ListerHaulables.ThingsPotentiallyNeedingHauling().Where(item
                                                                                                   => !job.targetQueueA.Contains(item) && !FireUtility.IsBurning(item) &&
                                                                                                   ((cart != null && cart.allowances.Allows(item)) || cart == null) &&
                                                                                                   slotGroup.Settings.AllowedToAccept(item) &&
                                                                                                   pawn.CanReserveAndReach(item, PathEndMode.Touch, DangerUtility.NormalMaxDanger(pawn)) &&
                                                                                                   center.DistanceToSquared(item.Position) <= ValidDistance))
                    {
                        job.targetQueueA.Add(item);
                        if (reservedMaxItem + job.targetQueueA.Count >= maxItem)
                        {
                            break;
                        }
                    }

                    //Find storage cell
                    Trace.AppendLine("Start Finding storage cell");
                    if (reservedMaxItem + job.targetQueueA.Count > thresholdItem)
                    {
                        List <IntVec3> availableCells = new List <IntVec3>();
                        foreach (IntVec3 cell in slotGroup.CellsList.Where(cell => ReservationUtility.CanReserve(pawn, cell) && cell.Standable() && cell.GetStorable() == null))
                        {
                            job.targetQueueB.Add(cell);
                            if (job.targetQueueB.Count >= job.targetQueueA.Count)
                            {
                                break;
                            }
                        }
                        flag1 = true;
                        break;
                    }
                    else
                    {
                        job.targetQueueA.Clear();
                    }
                }
                if (flag1)
                {
                    break;
                }
            }
            Trace.AppendLine("Elapsed Time");
            Trace.stopWatchStop();

            //Check job is valid
            if (!job.targetQueueA.NullOrEmpty() && reservedMaxItem + job.targetQueueA.Count > thresholdItem &&
                !job.targetQueueB.NullOrEmpty())
            {
                Trace.AppendLine("Hauling Job is issued");
                Trace.LogMessage();
                return(job);
            }
            if (cart != null && job.def == jobDefHaulWithCart && !cart.IsInValidStorage())
            {
                Trace.AppendLine("In DismountInBase: ");
                return(DismountInBase(pawn, cart));
            }

            if (job.targetQueueA.NullOrEmpty())
            {
                JobFailReason.Is(ToolsForHaulUtility.NoHaulable);
            }
            else if (reservedMaxItem + job.targetQueueA.Count <= thresholdItem)
            {
                JobFailReason.Is(ToolsForHaulUtility.TooLittleHaulable);
            }
            else if (job.targetQueueB.NullOrEmpty())
            {
                JobFailReason.Is(ToolsForHaulUtility.NoEmptyPlaceLowerTrans);
            }
            Trace.AppendLine("No Job. Reason: " + JobFailReason.Reason);
            Trace.LogMessage();
            return((Job)null);
        }
        protected override Job TryGiveTerminalJob(Pawn pawn)
        {
            Thing closestHaulable;
            Job   jobCollectThing   = new Job(DefDatabase <JobDef> .GetNamed("CollectThing"));
            Job   jobDropInCell     = new Job(DefDatabase <JobDef> .GetNamed("DropInCell"));
            Job   jobDismountInBase = new Job(DefDatabase <JobDef> .GetNamed("DismountInBase"));

            jobCollectThing.maxNumToCarry = 99999;
            jobCollectThing.haulMode      = HaulMode.ToCellStorage;


            //Find Available Carrier
            Vehicle_Cargo carrier = Find.ListerThings.AllThings.Find((Thing t)
                                                                     => (t.TryGetComp <CompMountable>() != null && t.TryGetComp <CompMountable>().Driver == pawn)) as Vehicle_Cargo;

            //No Carrier
            if (carrier == null)
            {
                //Log.Message("No Carrier");
                return(null);
            }
            jobCollectThing.targetC   = carrier;
            jobDropInCell.targetC     = carrier;
            jobDismountInBase.targetA = carrier;

            //collectThing Predicate
            Predicate <Thing> predicate = (Thing t)
                                          => (!t.IsForbidden(pawn.Faction) && !t.IsInAnyStorage() &&
                                              pawn.CanReserve(t) && carrier.storage.CanAcceptAnyOf(t));

            //Log.Message("flagInProgressDrop" + flagInProgressDrop);
            if (carrier.storage.TotalStackCount < carrier.GetMaxStackCount && carrier.storage.Contents.Count() < carrier.maxItem &&
                !ListerHaulables.ThingsPotentiallyNeedingHauling().NullOrEmpty() && flagInProgressDrop == false)
            {
                //Log.Message("Finding Haulable");
                closestHaulable = GenClosest.ClosestThing_Global_Reachable(pawn.Position,
                                                                           ListerHaulables.ThingsPotentiallyNeedingHauling(),
                                                                           PathMode.ClosestTouch,
                                                                           TraverseParms.For(pawn, Danger.Deadly, false),
                                                                           9999,
                                                                           predicate);
                if (closestHaulable == null)
                {
                    //Log.Message("No Haulable");
                    return(null);
                }
                jobCollectThing.targetA = closestHaulable;
                return(jobCollectThing);
            }
            else
            {
                //Log.Message("flagInProgressDrop" + flagInProgressDrop);
                flagInProgressDrop = true;
                if (carrier.storage.Contents.Count() <= 0)
                {
                    flagInProgressDrop = false;
                    //Log.Message("End Progress Drop");
                    if (ListerHaulables.ThingsPotentiallyNeedingHauling().NullOrEmpty())
                    {
                        return(jobDismountInBase);
                    }
                    return(null);
                }

                foreach (Zone zone in Find.ZoneManager.AllZones)
                {
                    if (zone is Zone_Stockpile)
                    {
                        foreach (var zoneCell in zone.cells)
                        {
                            Thing dropThing = carrier.storage.Contents.Last();

                            if (zoneCell.IsValidStorageFor(dropThing) && pawn.CanReserve(zoneCell))
                            {
                                jobDropInCell.targetA = dropThing;
                                jobDropInCell.targetB = zoneCell;
                                return(jobDropInCell);
                            }
                        }
                    }
                }

                //No zone for stock
                //Log.Message("No Zone");
                return(null);
            }
        }
        protected override Job TryGiveJob(Pawn pawn)
        {
            Predicate <Thing> validator = (Thing t) => !t.IsForbidden(pawn) && HaulAIUtility.PawnCanAutomaticallyHaulFast(pawn, t);
            //Start my code
            Thing        thing     = null;
            List <Thing> things    = ListerHaulables.ThingsPotentiallyNeedingHauling();
            List <Thing> degrade   = new List <Thing>();
            List <Thing> undegrade = new List <Thing>();

            foreach (Thing t in things)
            {
                if (t.GetStatValue(StatDefOf.DeteriorationRate) > 0)
                {
                    degrade.Add(t);
                }
                else
                {
                    undegrade.Add(t);
                }
            }
            //Loop through all haul areas in order
            foreach (Area a in AreaFinder.getHaulAreas())
            {
                //Check if got degradable item
                thing = GenClosest.ClosestThing_Global_Reachable(pawn.Position, AreaFinder.searcher(a, degrade), PathEndMode.OnCell, TraverseParms.For(pawn, Danger.Deadly, TraverseMode.ByPawn, false), 9999f, validator, null);
                if (thing != null)
                {
                    break;
                }

                //Check if got undegradable item
                thing = GenClosest.ClosestThing_Global_Reachable(pawn.Position, AreaFinder.searcher(a, undegrade), PathEndMode.OnCell, TraverseParms.For(pawn, Danger.Deadly, TraverseMode.ByPawn, false), 9999f, validator, null);
                if (thing != null)
                {
                    break;
                }
            }
            if (thing == null)
            {
                thing = GenClosest.ClosestThing_Global_Reachable(pawn.Position, degrade, PathEndMode.OnCell, TraverseParms.For(pawn, Danger.Deadly, TraverseMode.ByPawn, false), 9999f, validator, null);
                if (thing == null)
                {
                    thing = GenClosest.ClosestThing_Global_Reachable(pawn.Position, undegrade, PathEndMode.OnCell, TraverseParms.For(pawn, Danger.Deadly, TraverseMode.ByPawn, false), 9999f, validator, null);
                }
            }

            /* old 50 cell code
             * Thing thing = GenClosest.ClosestThing_Global_Reachable(pawn.Position, degrade, PathEndMode.OnCell, TraverseParms.For(pawn, Danger.Deadly, TraverseMode.ByPawn, false), 50f, validator, null);
             * if (thing == null)
             * {
             *  thing = GenClosest.ClosestThing_Global_Reachable(pawn.Position, undegrade, PathEndMode.OnCell, TraverseParms.For(pawn, Danger.Deadly, TraverseMode.ByPawn, false), 50f, validator, null);
             *  if (thing == null)
             *  {
             *      thing = GenClosest.ClosestThing_Global_Reachable(pawn.Position, degrade, PathEndMode.OnCell, TraverseParms.For(pawn, Danger.Deadly, TraverseMode.ByPawn, false), 9999f, validator, null);
             *      if (thing == null)
             *      {
             *          thing = GenClosest.ClosestThing_Global_Reachable(pawn.Position, undegrade, PathEndMode.OnCell, TraverseParms.For(pawn, Danger.Deadly, TraverseMode.ByPawn, false), 9999f, validator, null);
             *      }
             *  }
             * }*/
            //End my code
            if (thing != null)
            {
                return(HaulAIUtility.HaulToStorageJob(pawn, thing));
            }
            return(null);
        }
Example #10
0
        public static Job HaulWithTools(Pawn pawn, Vehicle_Cart cart = null, Thing haulThing = null)
        {
            Trace.stopWatchStart();

            //Job Setting
            bool                UseBackpack = false;
            JobDef              jobDef      = null;
            TargetInfo          targetC;
            int                 maxItem;
            int                 thresholdItem;
            int                 reservedMaxItem;
            IEnumerable <Thing> remainingItems;
            bool                ShouldDrop;
            Thing               lastItem = TryGetBackpackLastItem(pawn);
            Apparel_Backpack    backpack = TryGetBackpack(pawn);

            if (cart == null)
            {
                jobDef  = HaulJobDefOf.HaulWithBackpack;
                targetC = backpack;
                maxItem = backpack.MaxItem;
                // thresholdItem = (int)Math.Ceiling(maxItem * 0.5);
                thresholdItem   = 2;
                reservedMaxItem = backpack.slotsComp.slots.Count;
                remainingItems  = backpack.slotsComp.slots;
                ShouldDrop      = false;
                UseBackpack     = true;
                if (lastItem != null)
                {
                    for (int i = 0; i < backpack.slotsComp.slots.Count; i++)
                    {
                        if (backpack.slotsComp.slots[i] == lastItem && reservedMaxItem - (i + 1) <= 0)
                        {
                            ShouldDrop = false;
                            break;
                        }
                    }
                }
            }
            else
            {
                if (cart.mountableComp.IsMounted)
                {
                    jobDef = cart.mountableComp.Driver.RaceProps.Animal
                        ? HaulJobDefOf.HaulWithAnimalCart
                        : HaulJobDefOf.HaulWithCart;
                }
                else
                {
                    jobDef = HaulJobDefOf.HaulWithCart;
                }

                targetC = cart;

                maxItem         = cart.MaxItem;
                thresholdItem   = (int)Math.Ceiling(maxItem * 0.25);
                reservedMaxItem = cart.storage.Count;
                remainingItems  = cart.storage;


                ShouldDrop = reservedMaxItem > 0 ? true : false;
            }
            Job job = new Job(jobDef)
            {
                targetQueueA = new List <TargetInfo>(),
                targetQueueB = new List <TargetInfo>(),
                targetC      = targetC
            };

            if (UseBackpack)
            {
                job.numToBringList = new List <int>();
            }

            Trace.AppendLine(pawn.LabelCap + " In HaulWithTools: " + jobDef.defName + "\n"
                             + "MaxItem: " + maxItem + " reservedMaxItem: " + reservedMaxItem);

            //Drop remaining item
            if (ShouldDrop)
            {
                Trace.AppendLine("Start Drop remaining item");
                bool startDrop = false;
                for (int i = 0; i < remainingItems.Count(); i++)
                {
                    if (UseBackpack && startDrop == false)
                    {
                        if (remainingItems.ElementAt(i) == lastItem)
                        {
                            startDrop = true;
                        }
                        else
                        {
                            continue;
                        }
                    }
                    IntVec3 storageCell = FindStorageCell(pawn, remainingItems.ElementAt(i), job.targetQueueB);
                    if (storageCell == IntVec3.Invalid)
                    {
                        break;
                    }
                    job.targetQueueB.Add(storageCell);
                }
                if (!job.targetQueueB.NullOrEmpty())
                {
                    Trace.AppendLine("Dropping Job is issued");
                    Trace.LogMessage();
                    return(job);
                }
                if (!UseBackpack && job.def == HaulJobDefOf.HaulWithCart && !cart.IsInValidStorage())
                {
                    Trace.AppendLine("In DismountInBase");
                    return(DismountInBase(pawn, cart));
                }
                JobFailReason.Is(NoEmptyPlaceLowerTrans);
                Trace.AppendLine("End Drop remaining item");
                Trace.AppendLine("No Job. Reason: " + JobFailReason.Reason);
                Trace.LogMessage();
                return(null);
            }

            //Collect item
            Trace.AppendLine("Start Collect item");
            IntVec3 searchPos;

            if (haulThing != null)
            {
                searchPos = haulThing.Position;
            }
            else if (!UseBackpack)
            {
                searchPos = cart.Position;
            }
            else
            {
                searchPos = pawn.Position;
            }
            foreach (SlotGroup slotGroup in Find.SlotGroupManager.AllGroupsListInPriorityOrder)
            {
                Trace.AppendLine("Start searching slotGroup");
                if (slotGroup.CellsList.Count - slotGroup.HeldThings.Count() < maxItem)
                {
                    continue;
                }

                //Counting valid items
                Trace.AppendLine("Start Counting valid items");
                int thingsCount =
                    ListerHaulables.ThingsPotentiallyNeedingHauling()
                    .Count(item => slotGroup.Settings.AllowedToAccept(item));

                //Finding valid items
                Trace.AppendLine("Start Finding valid items");
                if (thingsCount > thresholdItem)
                {
                    Thing thing;
                    if (haulThing == null)
                    {
                        //ClosestThing_Global_Reachable Configuration
                        Predicate <Thing> predicate = item
                                                      => !job.targetQueueA.Contains(item) && !item.IsBurning() &&
                                                      !item.IsInAnyStorage() &&
                                                      (UseBackpack
                                   ? item.def.thingCategories.Exists(
                                                           category =>
                                                           backpack.slotsComp.Properties.allowedThingCategoryDefs.Exists(
                                                               subCategory =>
                                                               subCategory.ThisAndChildCategoryDefs.Contains(category))
                                                           &&
                                                           !backpack.slotsComp.Properties.forbiddenSubThingCategoryDefs.Exists(
                                                               subCategory =>
                                                               subCategory.ThisAndChildCategoryDefs.Contains(category)))
                                   : cart.allowances.Allows(item)) &&
                                                      !item.IsForbidden(pawn.Faction) &&
                                                      slotGroup.Settings.AllowedToAccept(item) &&
                                                      pawn.CanReserveAndReach(item, PathEndMode.Touch, pawn.NormalMaxDanger());
                        //&& !(item is UnfinishedThing && ((UnfinishedThing)item).BoundBill != null)
                        //&& (item.def.IsNutritionSource && !SocialProperness.IsSociallyProper(item, pawn, false, false));
                        thing = GenClosest.ClosestThing_Global_Reachable(searchPos,
                                                                         ListerHaulables.ThingsPotentiallyNeedingHauling(),
                                                                         PathEndMode.ClosestTouch,
                                                                         TraverseParms.For(pawn, pawn.NormalMaxDanger()),
                                                                         9999,
                                                                         predicate);
                        if (thing == null)
                        {
                            continue;
                        }
                    }
                    else
                    {
                        thing = haulThing;
                    }

                    //Find StorageCell
                    IntVec3 storageCell = FindStorageCell(pawn, thing, job.targetQueueB);
                    if (storageCell == IntVec3.Invalid)
                    {
                        break;
                    }

                    //Add Queue & Reserve
                    job.targetQueueA.Add(thing);
                    //for backpacks
                    if (UseBackpack)
                    {
                        job.numToBringList.Add(thing.def.stackLimit);
                    }

                    job.targetQueueB.Add(storageCell);


                    IntVec3 center = thing.Position;

                    //Enqueue SAME items in valid distance
                    Trace.AppendLine("Start Enqueuing SAME items in valid distance");
                    foreach (Thing item in ListerHaulables.ThingsPotentiallyNeedingHauling().Where(item
                                                                                                   => !job.targetQueueA.Contains(item) && !item.IsBurning() &&
                                                                                                   !item.IsInAnyStorage() &&
                                                                                                   (UseBackpack
                               ? item.def.thingCategories.Exists(
                                                                                                        category =>
                                                                                                        backpack.slotsComp.Properties.allowedThingCategoryDefs.Exists(
                                                                                                            subCategory =>
                                                                                                            subCategory.ThisAndChildCategoryDefs.Contains(category))
                                                                                                        &&
                                                                                                        !backpack.slotsComp.Properties.forbiddenSubThingCategoryDefs.Exists(
                                                                                                            subCategory =>
                                                                                                            subCategory.ThisAndChildCategoryDefs.Contains(category)))
                               : cart.allowances.Allows(item)) &&
                                                                                                   !item.IsForbidden(pawn.Faction) &&
                                                                                                   slotGroup.Settings.AllowedToAccept(item) &&
                                                                                                   pawn.CanReserveAndReach(item, PathEndMode.Touch, pawn.NormalMaxDanger()) &&
                                                                                                   center.DistanceToSquared(item.Position) <= ValidDistance))
                    {
                        job.targetQueueA.Add(item);
                        if (UseBackpack)
                        {
                            job.numToBringList.Add(item.def.stackLimit);
                        }


                        reservedMaxItem++;

                        if (reservedMaxItem + job.targetQueueA.Count >= maxItem)
                        {
                            break;
                        }
                    }

                    //Enqueue other items in valid distance
                    if (reservedMaxItem + job.targetQueueA.Count < maxItem)
                    {
                        Trace.AppendLine("Start Enqueuing items in valid distance");

                        foreach (Thing item in ListerHaulables.ThingsPotentiallyNeedingHauling().Where(item
                                                                                                       => !job.targetQueueA.Contains(item) && !item.IsBurning() &&
                                                                                                       !item.IsInAnyStorage() &&
                                                                                                       (UseBackpack
                                   ? item.def.thingCategories.Exists(
                                                                                                            category =>
                                                                                                            backpack.slotsComp.Properties.allowedThingCategoryDefs.Exists(
                                                                                                                subCategory =>
                                                                                                                subCategory.ThisAndChildCategoryDefs.Contains(category))
                                                                                                            &&
                                                                                                            !backpack.slotsComp.Properties.forbiddenSubThingCategoryDefs.Exists(
                                                                                                                subCategory =>
                                                                                                                subCategory.ThisAndChildCategoryDefs.Contains(category)))
                                   : cart.allowances.Allows(item)) &&
                                                                                                       !item.IsForbidden(pawn.Faction) &&
                                                                                                       slotGroup.Settings.AllowedToAccept(item) &&
                                                                                                       pawn.CanReserveAndReach(item, PathEndMode.Touch, pawn.NormalMaxDanger()) &&
                                                                                                       center.DistanceToSquared(item.Position) <= ValidDistance))
                        {
                            job.targetQueueA.Add(item);
                            if (UseBackpack)
                            {
                                job.numToBringList.Add(item.def.stackLimit);
                            }
                            reservedMaxItem++;

                            if (reservedMaxItem + job.targetQueueA.Count >= maxItem)
                            {
                                break;
                            }
                        }
                    }

                    //Also enqueue items in whiche are not in their best storage cell
                    if (reservedMaxItem + job.targetQueueA.Count < maxItem)
                    {
                        Trace.AppendLine("Start Enqueuing items in valid distance & not in best storage cell");
                        foreach (Thing item in ListerHaulables.ThingsPotentiallyNeedingHauling().Where(item
                                                                                                       => !job.targetQueueA.Contains(item) && !item.IsBurning() &&
                                                                                                       !item.IsInValidBestStorage() &&
                                                                                                       (UseBackpack
                                   ? item.def.thingCategories.Exists(
                                                                                                            category =>
                                                                                                            backpack.slotsComp.Properties.allowedThingCategoryDefs.Exists(
                                                                                                                subCategory =>
                                                                                                                subCategory.ThisAndChildCategoryDefs.Contains(category))
                                                                                                            &&
                                                                                                            !backpack.slotsComp.Properties.forbiddenSubThingCategoryDefs.Exists(
                                                                                                                subCategory =>
                                                                                                                subCategory.ThisAndChildCategoryDefs.Contains(category)))
                                   : cart.allowances.Allows(item)) &&
                                                                                                       !item.IsForbidden(pawn.Faction) &&
                                                                                                       slotGroup.Settings.AllowedToAccept(item) &&
                                                                                                       pawn.CanReserveAndReach(item, PathEndMode.Touch, pawn.NormalMaxDanger()) &&
                                                                                                       center.DistanceToSquared(item.Position) <= ValidDistance))
                        {
                            job.targetQueueA.Add(item);
                            if (UseBackpack)
                            {
                                job.numToBringList.Add(item.def.stackLimit);
                            }
                            reservedMaxItem++;

                            if (reservedMaxItem + job.targetQueueA.Count >= maxItem)
                            {
                                break;
                            }
                        }
                    }

                    //Find storage cell
                    Trace.AppendLine("Start Finding storage cell");
                    if (reservedMaxItem + job.targetQueueA.Count > thresholdItem)
                    {
                        foreach (
                            IntVec3 cell in
                            slotGroup.CellsList.Where(
                                cell =>
                                pawn.CanReserveAndReach(cell, PathEndMode.ClosestTouch, Danger.Some) &&
                                cell.Standable() && cell.GetStorable() == null))
                        {
                            StoragePriority currentPriority = HaulAIUtility.StoragePriorityAtFor(thing.Position, thing);
                            IntVec3         storeCell       = cell;
                            if (
                                !StoreUtility.TryFindBestBetterStoreCellFor(thing, pawn, currentPriority, pawn.Faction,
                                                                            out storeCell))
                            {
                                if (cell.InAllowedArea(pawn))
                                {
                                    job.targetQueueB.Add(cell);
                                }
                                if (job.targetQueueB.Count >= job.targetQueueA.Count)
                                {
                                    break;
                                }
                            }
                            else
                            {
                                if (storeCell.InAllowedArea(pawn))
                                {
                                    job.targetQueueB.Add(storeCell);
                                }
                                if (job.targetQueueB.Count >= job.targetQueueA.Count)
                                {
                                    break;
                                }
                            }
                        }
                        break;
                    }
                    job.targetQueueA.Clear();
                }
            }
            Trace.AppendLine("Elapsed Time");
            Trace.stopWatchStop();

            //Check job is valid
            if (!job.targetQueueA.NullOrEmpty() && reservedMaxItem + job.targetQueueA.Count > thresholdItem &&
                !job.targetQueueB.NullOrEmpty())
            {
                Trace.AppendLine("Hauling Job is issued");
                Trace.LogMessage();
                return(job);
            }
            if (cart != null && job.def == HaulJobDefOf.HaulWithCart && !cart.IsInValidStorage())
            {
                Trace.AppendLine("In DismountInBase: ");
                return(DismountInBase(pawn, cart));
            }

            if (job.targetQueueA.NullOrEmpty())
            {
                JobFailReason.Is("NoHaulable".Translate());
            }
            else if (reservedMaxItem + job.targetQueueA.Count <= thresholdItem)
            {
                JobFailReason.Is(TooLittleHaulable);
            }
            else if (job.targetQueueB.NullOrEmpty())
            {
                JobFailReason.Is(NoEmptyPlaceLowerTrans);
            }
            Trace.AppendLine("No Job. Reason: " + JobFailReason.Reason);
            Trace.LogMessage();
            return(null);
        }
        public override Job JobOnThing(Pawn pawn, Thing t)
        {
            if (!(t is Vehicle_Cargo))
            {
                return(null);
            }
            Vehicle_Cargo       carrier        = t as Vehicle_Cargo;
            List <Thing>        haulables      = ListerHaulables.ThingsPotentiallyNeedingHauling();
            IEnumerable <Thing> remainingItems = carrier.storage.Contents;
            //bool IsMountedVehicle = ((carrier.GetComp<CompMountable>().Driver == pawn)? true: false);
            int reservedStackCount = carrier.storage.TotalStackCount;
            int reservedMaxItem    = carrier.storage.Contents.Count();
            Job jobDismountInBase  = new Job(DefDatabase <JobDef> .GetNamed("DismountInBase"));
            Job jobCollect         = new Job(DefDatabase <JobDef> .GetNamed("Collect"));

            jobCollect.maxNumToCarry = 99999;
            jobCollect.haulMode      = HaulMode.ToCellStorage;
            jobCollect.targetQueueA  = new List <TargetInfo>();
            jobCollect.targetQueueB  = new List <TargetInfo>();

            //Set carrier
            jobDismountInBase.targetA = carrier;
            jobCollect.targetC        = carrier;
            ReservationUtility.Reserve(pawn, t);

            //If IgnoreForbidden is true, add forbidden
            if (carrier.ignoreForbidden)
            {
                List <Thing> forbiddens = Find.ListerThings.AllThings.FindAll((Thing thing) =>
                                                                              (thing.TryGetComp <CompForbiddable>() != null && thing.TryGetComp <CompForbiddable>().Forbidden == true));
                haulables = forbiddens.Concat(haulables).ToList();

                /*string logStr = "";
                 * foreach (var forbidden in forbiddens)
                 *  logStr += forbidden.ThingID;
                 * Log.Message("Haulable: " + logStr);*/
            }

            //Drop remaining item
            foreach (var remainingItem in remainingItems)
            {
                IntVec3 storageCell = new IntVec3(-1000, -1000, -1000);
                foreach (Zone zone in Find.ZoneManager.AllZones)
                {
                    if (storageCell.IsValid)
                    {
                        break;
                    }
                    if (zone is Zone_Stockpile)
                    {
                        foreach (var zoneCell in zone.cells)
                        {
                            if (!jobCollect.targetQueueB.Contains(zoneCell) && zoneCell.IsValidStorageFor(remainingItem) && pawn.CanReserve(zoneCell))
                            {
                                storageCell = zoneCell;
                                break;
                            }
                        }
                    }
                }
                if (!storageCell.IsValid)
                {
                    break;
                }

                //Just drop, not collect. It was already collected
                //jobCollect.targetQueueA.Add(remainingItem);
                //ReservationUtility.Reserve(pawn, remainingItem, ReservationType.Total);
                jobCollect.targetQueueB.Add(storageCell);
                ReservationUtility.Reserve(pawn, storageCell);
            }
            if (!jobCollect.targetQueueB.NullOrEmpty())
            {
                return(jobCollect);
            }

            //collectThing Predicate
            Predicate <Thing> predicate = (Thing item)
                                          => ((carrier.ignoreForbidden || !item.IsForbidden(pawn.Faction)) &&
                                              !item.IsInValidStorage() && pawn.CanReserve(item) &&
                                              carrier.storage.CanAcceptAnyOf(item));

            //Collect and drop item
            while (!haulables.NullOrEmpty() && reservedStackCount < carrier.GetMaxStackCount && reservedMaxItem < carrier.maxItem)
            {
                IntVec3 storageCell     = new IntVec3(-1000, -1000, -1000);
                Thing   closestHaulable = null;
                //Log.Message("reservedStackCount, reservedMaxItem :" + reservedStackCount + ',' +  reservedMaxItem);
                closestHaulable = GenClosest.ClosestThing_Global_Reachable(pawn.Position,
                                                                           haulables,
                                                                           PathMode.ClosestTouch,
                                                                           TraverseParms.For(pawn, Danger.Deadly, false),
                                                                           9999,
                                                                           predicate);
                if (closestHaulable == null)
                {
                    break;
                }

                if (!jobCollect.targetQueueB.NullOrEmpty())
                {
                    foreach (TargetInfo target in jobCollect.targetQueueB)
                    {
                        if (storageCell.IsValid)
                        {
                            break;
                        }
                        foreach (var adjCell in GenAdjFast.AdjacentCells8Way(target))
                        {
                            if (!jobCollect.targetQueueB.Contains(adjCell) && adjCell.IsValidStorageFor(closestHaulable) && pawn.CanReserve(adjCell))
                            {
                                storageCell = adjCell;
                                break;
                            }
                        }
                    }
                }

                foreach (Zone zone in Find.ZoneManager.AllZones)
                {
                    if (storageCell.IsValid)
                    {
                        break;
                    }
                    if (zone is Zone_Stockpile)
                    {
                        foreach (var zoneCell in zone.cells)
                        {
                            if (!jobCollect.targetQueueB.Contains(zoneCell) && zoneCell.IsValidStorageFor(closestHaulable) && pawn.CanReserve(zoneCell))
                            {
                                storageCell = zoneCell;
                                //Log.Message("storageCell: " + storageCell);
                                break;
                            }
                        }
                    }
                }
                //No Storage
                if (!storageCell.IsValid)
                {
                    break;
                }

                jobCollect.targetQueueA.Add(closestHaulable);
                ReservationUtility.Reserve(pawn, closestHaulable);
                haulables.Remove(closestHaulable);
                jobCollect.targetQueueB.Add(storageCell);
                ReservationUtility.Reserve(pawn, storageCell);
                reservedMaxItem++;
                reservedStackCount += closestHaulable.stackCount;
            }

            //No haulables or zone
            if (jobCollect.targetQueueA.NullOrEmpty() || jobCollect.targetQueueB.NullOrEmpty())
            {
                foreach (Zone zone in Find.ZoneManager.AllZones)
                {
                    if (jobDismountInBase.targetB != null)
                    {
                        break;
                    }
                    if (zone is Zone_Stockpile)
                    {
                        foreach (var zoneCell in zone.cells)
                        {
                            Thing dropThing = carrier;
                            if (zoneCell.IsValidStorageFor(dropThing) && pawn.CanReserve(zoneCell))
                            {
                                ReservationUtility.Reserve(pawn, zoneCell);
                                jobDismountInBase.targetB = zoneCell;
                                break;
                            }
                        }
                    }
                }

                //Move cargo in Base
                if (!carrier.IsInValidStorage() && jobDismountInBase.targetB != null)
                {
                    return(jobDismountInBase);
                }

                //No job, no move to cargo
                if (Find.Reservations.IsReserved(carrier, pawn.Faction))
                {
                    Find.Reservations.Release(carrier, pawn);
                }
                return(null);
            }

            return(jobCollect);
        }
Example #12
0
        public override Job JobOnThing(Pawn pawn, Thing t)
        {
            Vehicle_Cart cart = null;

            if (!HaulAIUtility.PawnCanAutomaticallyHaulFast(pawn, t))
            {
                return(null);
            }

            // Vehicle selection

            if (ToolsForHaulUtility.IsDriver(pawn))
            {
                cart = ToolsForHaulUtility.GetCartByDriver(pawn);

                if (cart == null)
                {
                    //  JobFailReason.Is("Can't haul with military vehicle");
                    return(ToolsForHaulUtility.DismountInBase(pawn, MapComponent_ToolsForHaul.currentVehicle[pawn]));
                }
            }


            if (cart == null)
            {
                cart = RightTools.GetRightVehicle(pawn, WorkTypeDefOf.Hauling, t) as Vehicle_Cart;

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



            if (cart.IsBurning())
            {
                JobFailReason.Is(ToolsForHaulUtility.BurningLowerTrans);
                return(null);
            }

            if (!cart.allowances.Allows(t))
            {
                JobFailReason.Is("Cart does not allow that thing");
                return(null);
            }

            if (ListerHaulables.ThingsPotentiallyNeedingHauling().Count == 0 && cart.storage.Count == 0)
            {
                JobFailReason.Is("NoHaulable".Translate());
                return(null);
            }

            if (Find.SlotGroupManager.AllGroupsListInPriorityOrder.Count == 0)
            {
                JobFailReason.Is(ToolsForHaulUtility.NoEmptyPlaceLowerTrans);
                return(null);
            }

            if (ToolsForHaulUtility.AvailableAnimalCart(cart) || ToolsForHaulUtility.AvailableVehicle(pawn, cart))
            {
                return(ToolsForHaulUtility.HaulWithTools(pawn, cart, t));
            }
            JobFailReason.Is(ToolsForHaulUtility.NoAvailableCart);
            return(null);
        }
Example #13
0
 public override IEnumerable <Thing> PotentialWorkThingsGlobal(Pawn pawn)
 {
     //return ToolsForHaulUtility.Cart();
     return(ListerHaulables.ThingsPotentiallyNeedingHauling());
 }