public static bool AvailableAnimalCart(Vehicle_Cart cart)
        {
            Pawn Driver = (cart.TryGetComp<CompMountable>().IsMounted) ? cart.TryGetComp<CompMountable>().Driver : null;
            if (Driver == null)
                return false;

            return Driver.RaceProps.Animal && PawnUtility.CasualInterruptibleNow(Driver)
                && Driver.needs.food.CurCategory < HungerCategory.Starving
                && Driver.needs.rest.CurCategory < RestCategory.VeryTired
                && !Driver.health.ShouldBeTreatedNow;
        }
        public static bool AvailableAnimalCart(Vehicle_Cart cart)
        {
            Pawn Driver = (cart.TryGetComp <CompMountable>().IsMounted) ? cart.TryGetComp <CompMountable>().Driver : null;

            if (Driver == null)
            {
                return(false);
            }

            return(Driver.RaceProps.Animal && PawnUtility.CasualInterruptibleNow(Driver) &&
                   Driver.needs.food.CurCategory < HungerCategory.Starving &&
                   Driver.needs.rest.CurCategory < RestCategory.VeryTired &&
                   !Driver.health.ShouldBeTendedNow);
        }
 public static bool AvailableCart(Vehicle_Cart cart, Pawn pawn)
 {
     return(!cart.TryGetComp <CompMountable>().IsMounted || cart.TryGetComp <CompMountable>().Driver == pawn);
 }
        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);
        }
 public static bool AvailableCart(Vehicle_Cart cart, Pawn pawn)
 {
     return (!cart.TryGetComp<CompMountable>().IsMounted || cart.TryGetComp<CompMountable>().Driver == pawn);
 }
        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;
        }
Example #7
0
        protected override IEnumerable <Toil> MakeNewToils()
        {
            Vehicle_Cart cart   = CurJob.GetTarget(CartInd).Thing as Vehicle_Cart;
            Job          jobNew = new Job();

            ///
            //Set fail conditions
            ///

            this.FailOnDestroyed(CartInd);
            this.FailOn(() => !cart.mountableComp.IsMounted);
            //Note we only fail on forbidden if the target doesn't start that way
            //This helps haul-aside jobs on forbidden items
            if (!TargetThingA.IsForbidden(pawn.Faction))
            {
                this.FailOnForbidden(CartInd);
            }

            ///
            //Define Toil
            ///

            Toil releaseAnimalCart   = Toils_Cart.ReleaseAnimalCart(CartInd);
            Toil checkCartEmpty      = Toils_Jump.JumpIf(releaseAnimalCart, () => cart.storage.Count <= 0);
            Toil checkStoreCellEmpty = Toils_Jump.JumpIf(releaseAnimalCart, () => CurJob.GetTargetQueue(StoreCellInd).NullOrEmpty());
            Toil checkHaulableEmpty  = Toils_Jump.JumpIf(checkStoreCellEmpty, () => CurJob.GetTargetQueue(HaulableInd).NullOrEmpty());

            ///
            //Toils Start
            ///

            //Reserve thing to be stored and storage cell
            yield return(Toils_Reserve.Reserve(CartInd));

            yield return(Toils_Reserve.ReserveQueue(HaulableInd));

            yield return(Toils_Reserve.ReserveQueue(StoreCellInd));

            yield return(Toils_Goto.GotoThing(CartInd, PathEndMode.Touch)
                         .FailOn(() => cart.Destroyed || !cart.TryGetComp <CompMountable>().IsMounted));

            //JumpIf toilCheckStoreCellEmpty
            yield return(checkHaulableEmpty);

            //Collect TargetQueue
            {
                Toil extractA = Toils_Collect.Extract(HaulableInd);
                yield return(extractA);

                Toil callAnimalCartForCollect = Toils_Cart.CallAnimalCart(CartInd, HaulableInd)
                                                .FailOnDestroyed(HaulableInd);
                yield return(callAnimalCartForCollect);

                yield return(Toils_Goto.GotoThing(HaulableInd, PathEndMode.ClosestTouch)
                             .FailOnDestroyed(HaulableInd));

                yield return(Toils_Cart.WaitAnimalCart(CartInd, HaulableInd));

                yield return(Toils_Collect.CollectInCarrier(CartInd, HaulableInd));

                yield return(Toils_Collect.CheckDuplicates(callAnimalCartForCollect, CartInd, HaulableInd));

                yield return(Toils_Jump.JumpIfHaveTargetInQueue(HaulableInd, extractA));
            }

            //JumpIf releaseAnimalCart
            yield return(checkStoreCellEmpty);

            //Drop TargetQueue
            {
                yield return(checkCartEmpty);

                Toil extractB = Toils_Collect.Extract(StoreCellInd);
                yield return(extractB);

                Toil callAnimalCartForDrop = Toils_Cart.CallAnimalCart(CartInd, StoreCellInd);
                yield return(callAnimalCartForDrop);

                yield return(Toils_Goto.GotoCell(StoreCellInd, PathEndMode.ClosestTouch)
                             .FailOnBurningImmobile(StoreCellInd));

                yield return(Toils_Cart.WaitAnimalCart(CartInd, HaulableInd));

                yield return(Toils_Collect.DropTheCarriedInCell(StoreCellInd, ThingPlaceMode.Direct, CartInd));

                yield return(Toils_Jump.JumpIfHaveTargetInQueue(StoreCellInd, checkCartEmpty));

                yield return(Toils_Collect.CheckNeedStorageCell(callAnimalCartForDrop, CartInd, StoreCellInd));
            }

            yield return(releaseAnimalCart);
        }