Exemplo n.º 1
0
        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);
        }
Exemplo n.º 2
0
        // OLD

        /* public static Toil CollectInInventory(TargetIndex HaulableInd)
         * {
         *
         *   Toil toil = new Toil();
         *   toil.initAction = () =>
         *   {
         *       Pawn actor = toil.actor;
         *       Job curJob = actor.jobs.curJob;
         *       Thing haulThing = curJob.GetTarget(HaulableInd).Thing;
         *
         *       //Check haulThing is human_corpse. If other race has apparel, It need to change
         *       if (haulThing.ThingID.IndexOf("Human_Corpse") <= -1 ? false : true)
         *       {
         *           Corpse corpse = (Corpse)haulThing;
         *           List<Apparel> wornApparel = corpse.innerPawn.apparel.WornApparel;
         *
         *           //Drop wornApparel. wornApparel cannot Add to container directly because it will be duplicated.
         *           corpse.innerPawn.apparel.DropAll(corpse.innerPawn.Position, false);
         *
         *           //Transfer in container
         *           foreach (Thing apparel in wornApparel)
         *           {
         *               if (actor.inventory.container.TryAdd(apparel))
         *               {
         *                   apparel.holder = actor.inventory.GetContainer();
         *                   apparel.holder.owner = actor.inventory;
         *               }
         *           }
         *       }
         *       //Collecting TargetIndex ind
         *       if (actor.inventory.container.TryAdd(haulThing))
         *       {
         *           haulThing.holder = actor.inventory.GetContainer();
         *           haulThing.holder.owner = actor.inventory;
         *       }
         *
         *   };
         *   toil.FailOn(() =>
         *   {
         *       Pawn actor = toil.actor;
         *       Job curJob = actor.jobs.curJob;
         *       Thing haulThing = curJob.GetTarget(HaulableInd).Thing;
         *
         *       if (!actor.inventory.container.CanAcceptAnyOf(haulThing))
         *           return true;
         *
         *
         *
         *       return false;
         *   });
         *   return toil;
         * }
         */
        public static Toil CollectInBackpack(TargetIndex HaulableInd, Apparel_Backpack backpack)
        {
            Toil toil = new Toil();

            toil.initAction = () =>
            {
                Pawn  actor     = toil.actor;
                Job   curJob    = actor.jobs.curJob;
                Thing haulThing = curJob.GetTarget(HaulableInd).Thing;


                //Collecting TargetIndex ind
                if (backpack.slotsComp.slots.TryAdd(haulThing))
                {
                    haulThing.holder       = backpack.slotsComp.GetContainer();
                    haulThing.holder.owner = backpack.slotsComp;
                }
            };
            toil.FailOn(() =>
            {
                Pawn actor      = toil.actor;
                Job curJob      = actor.jobs.curJob;
                Thing haulThing = curJob.GetTarget(HaulableInd).Thing;

                if (!backpack.slotsComp.slots.CanAcceptAnyOf(haulThing))
                {
                    return(true);
                }



                return(false);
            });
            return(toil);
        }
Exemplo n.º 3
0
        public static Toil CheckNeedStorageCell(Toil jumpToil, TargetIndex CarrierInd, TargetIndex StoreCellInd)
        {
            Toil toil = new Toil();

            toil.initAction = () =>
            {
                Pawn actor = toil.actor;

                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);
                }
                ThingContainer container = cart != null ? cart.storage : backpack.slotsComp.slots;
                if (container.Count == 0)
                {
                    return;
                }

                IntVec3 cell = ToolsForHaulUtility.FindStorageCell(actor, container.First());
                if (cell != IntVec3.Invalid)
                {
                    toil.actor.jobs.curJob.SetTarget(StoreCellInd, cell);
                    Find.Reservations.Reserve(actor, cell);
                    toil.actor.jobs.curDriver.JumpToToil(jumpToil);
                }
            };
            return(toil);
        }
Exemplo n.º 4
0
        public static Thing TryGetBackpackLastItem(Pawn pawn)
        {
            Apparel_Backpack backpack = TryGetBackpack(pawn);

            if (backpack == null)
            {
                return(null);
            }
            Thing lastItem        = null;
            int   lastItemInd     = -1;
            Thing foodInInventory = FoodUtility.BestFoodInInventory(pawn);

            if (backpack.slotsComp.slots.Count > 0)
            {
                if (backpack.numOfSavedItems > 0)
                {
                    lastItemInd = (backpack.numOfSavedItems >= backpack.MaxItem
                        ? backpack.slotsComp.slots.Count
                        : backpack.numOfSavedItems) - 1;
                    lastItem = backpack.slotsComp.slots[lastItemInd];
                }
                if (foodInInventory != null && backpack.numOfSavedItems < backpack.slotsComp.slots.Count &&
                    backpack.slotsComp.slots[lastItemInd + 1] == foodInInventory)
                {
                    lastItem = foodInInventory;
                }
            }
            return(lastItem);
        }
Exemplo n.º 5
0
        protected override IEnumerable <Toil> MakeNewToils()
        {
            Apparel_Backpack backpack = CurJob.GetTarget(BackpackInd).Thing as Apparel_Backpack;

            // no free slots
            this.FailOn(() => backpack.slotsComp.slots.Count >= backpack.MaxItem);

            // reserve resources
            yield return(Toils_Reserve.ReserveQueue(HaulableInd));

            // extract next target thing from targetQueue
            Toil toilExtractNextTarget = Toils_JobTransforms.ExtractNextTargetFromQueue(HaulableInd);

            yield return(toilExtractNextTarget);

            Toil toilGoToThing = Toils_Goto.GotoThing(HaulableInd, PathEndMode.ClosestTouch)
                                 .FailOnDespawnedOrNull(HaulableInd);

            yield return(toilGoToThing);

            Toil pickUpThingIntoSlot = new Toil
            {
                initAction = () =>
                {
                    if (!backpack.slotsComp.slots.TryAdd(CurJob.targetA.Thing))
                    {
                        EndJobWith(JobCondition.Incompletable);
                    }
                }
            };

            yield return(pickUpThingIntoSlot);

            yield return(Toils_Jump.JumpIfHaveTargetInQueue(HaulableInd, toilExtractNextTarget));
        }
        public override Job JobOnThing(Pawn pawn, Thing t)
        {
            if (t is Corpse)
            {
                return(null);
            }

            if (!HaulAIUtility.PawnCanAutomaticallyHaulFast(pawn, t))
            {
                return(null);
            }
            Apparel_Backpack backpack = ToolsForHaulUtility.TryGetBackpack(pawn);

            if (backpack != null)
            {
                if (
                    !t.def.thingCategories.Exists(
                        category =>
                        backpack.slotsComp.Properties.allowedThingCategoryDefs.Exists(
                            subCategory => subCategory.ThisAndChildCategoryDefs.Contains(category)) &&
                        !backpack.slotsComp.Properties.forbiddenSubThingCategoryDefs.Exists(
                            subCategory => subCategory.ThisAndChildCategoryDefs.Contains(category))))
                {
                    JobFailReason.Is("Backpack can't hold that thing");
                    return(null);
                }
                else
                {
                    return(ToolsForHaulUtility.HaulWithTools(pawn));
                }
            }

            JobFailReason.Is("NoBackpack".Translate());
            return(null);
        }
Exemplo n.º 7
0
        internal static bool TryDrop(this Pawn_ApparelTracker _this, Apparel ap, out Apparel resultingAp, IntVec3 pos, bool forbid = true)
        {
            // drop all toolbelt & backpack stuff so that it won't disappear
            Apparel_Backpack backpack = ap as Apparel_Backpack;

            Thing dropThing = null;

            if (backpack?.slotsComp?.slots?.Count >= 1)
            {
                foreach (Thing slot in backpack.slotsComp.slots)
                {
                    GenThing.TryDropAndSetForbidden(slot, pos, ThingPlaceMode.Near, out dropThing, forbid);
                }
            }

            if (!_this.WornApparel.Contains(ap))
            {
                Log.Warning(_this.pawn.LabelCap + " tried to drop apparel he didn't have: " + ap.LabelCap);
                resultingAp = null;
                return(false);
            }
            _this.WornApparel.Remove(ap);
            ap.wearer = null;
            Thing thing = null;
            bool  flag  = GenThing.TryDropAndSetForbidden(ap, pos, ThingPlaceMode.Near, out thing, forbid);

            resultingAp = (thing as Apparel);
            _this.ApparelChanged();
            if (flag && _this.pawn.outfits != null)
            {
                _this.pawn.outfits.forcedHandler.SetForced(ap, false);
            }
            Combat_Realism.CR_Utility.TryUpdateInventory(_this.pawn);     // Apparel was dropped, update inventory
            return(flag);
        }
Exemplo n.º 8
0
        private float GetStatFactor(Pawn thisPawn)
        {
            float result = 1f;

            if (MapComponent_ToolsForHaul.currentVehicle.ContainsKey(thisPawn))
            {
                Vehicle_Cart vehicleCart = MapComponent_ToolsForHaul.currentVehicle[thisPawn] as Vehicle_Cart;
                if (vehicleCart != null)
                {
                    if (vehicleCart.mountableComp.IsMounted && !vehicleCart.mountableComp.Driver.RaceProps.Animal && vehicleCart.mountableComp.Driver == thisPawn)
                    {
                        if (vehicleCart.IsCurrentlyMotorized())
                        {
                            result = Mathf.Clamp(vehicleCart.VehicleSpeed, 2f, 100f);
                        }
                        else
                        {
                            result = Mathf.Clamp(vehicleCart.VehicleSpeed, 0.5f, 1f);
                        }
                        return(result);
                    }
                }

                Vehicle_Turret vehicleTank = MapComponent_ToolsForHaul.currentVehicle[thisPawn] as Vehicle_Turret;
                if (vehicleTank != null)
                {
                    if (vehicleTank.mountableComp.IsMounted && !vehicleTank.mountableComp.Driver.RaceProps.Animal && vehicleTank.mountableComp.Driver == thisPawn)
                    {
                        if (vehicleTank.IsCurrentlyMotorized())
                        {
                            result = Mathf.Clamp(vehicleTank.VehicleSpeed, 2f, 100f);
                        }
                        else
                        {
                            result = Mathf.Clamp(vehicleTank.VehicleSpeed, 0.5f, 1f);
                        }
                        return(result);
                    }
                }
            }

            Apparel_Backpack  apparelBackpack   = ToolsForHaulUtility.TryGetBackpack(thisPawn);
            CompSlotsBackpack compSlotsBackpack = apparelBackpack?.slotsComp;

            if (compSlotsBackpack != null)
            {
                result = Mathf.Clamp(compSlotsBackpack.moveSpeedFactor - compSlotsBackpack.encumberPenalty, 0.1f, 1f);
            }

            CompInventory compInventory = thisPawn.TryGetComp <CompInventory>();

            if (compInventory != null)
            {
                result = Mathf.Clamp(compInventory.moveSpeedFactor - compInventory.encumberPenalty, 0.1f, 1f);
                return(result);
            }

            return(result);
        }
        internal static bool TryDrop(this Pawn_ApparelTracker _this, Apparel ap, out Apparel resultingAp, IntVec3 pos, bool forbid = true)
        {
            // drop all toolbelt & backpack stuff so that it won't disappear
            Apparel_Backpack backpack  = ap as Apparel_Backpack;
            Apparel_Toolbelt toolbelt  = ap as Apparel_Toolbelt;
            Thing            dropThing = null;

            if (backpack?.SlotsComp?.slots?.Count >= 1)
            {
                foreach (Thing slot in backpack.SlotsComp.slots)
                {
                    GenThing.TryDropAndSetForbidden(slot, pos, ap.Map, ThingPlaceMode.Near, out dropThing, forbid);
                }
            }

            if (toolbelt?.slotsComp?.slots?.Count >= 1)
            {
                foreach (Thing slot in toolbelt.slotsComp.slots)
                {
                    GenThing.TryDropAndSetForbidden(slot, pos, ap.Map, ThingPlaceMode.Near, out dropThing, forbid);
                }

                for (int i = MapComponent_ToolsForHaul.CachedToolEntries.Count - 1;
                     i >= 0;
                     i--)
                {
                    var entry = MapComponent_ToolsForHaul.CachedToolEntries[i];
                    if (entry.pawn == _this.pawn)
                    {
                        MapComponent_ToolsForHaul.CachedToolEntries.RemoveAt(i);
                    }
                }
            }


            if (!_this.WornApparel.Contains(ap))
            {
                Log.Warning(_this.pawn.LabelCap + " tried to drop apparel he didn't have: " + ap.LabelCap);
                resultingAp = null;
                return(false);
            }
            if (_this.pawn.MapHeld == null)
            {
                Log.Warning(_this.pawn.LabelCap + " tried to drop apparel but his MapHeld is null.");
                resultingAp = null;
                return(false);
            }
            ap.Notify_Stripped(_this.pawn);
            _this.Remove(ap);
            Thing thing  = null;
            bool  result = GenThing.TryDropAndSetForbidden(ap, pos, _this.pawn.MapHeld, ThingPlaceMode.Near, out thing, forbid);

            resultingAp = (thing as Apparel);

#if CR
            Combat_Realism.CR_Utility.TryUpdateInventory(_this.pawn);     // Apparel was dropped, update inventory
#endif
            return(result);
        }
        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);

            Apparel_Backpack backpack = ToolsForHaulUtility.TryGetBackpack(pawn);

            //Should skip pawn that don't have backpack.
            if (backpack == null)
            {
                return(true);
            }
            if (backpack.MaxItem - backpack.slotsComp.slots.Count == 0)
            {
                return(true);
            }
            return(false);
        }
        public static Toil DropTheCarriedFromBackpackInCell(
            TargetIndex StoreCellInd,
            ThingPlaceMode placeMode,
            Apparel_Backpack backpack)
        {
            Toil toil = new Toil();

            toil.initAction = () =>
            {
                Pawn actor  = toil.actor;
                Job  curJob = actor.jobs.curJob;
                if (backpack.SlotsComp.slots.Count <= 0)
                {
                    return;
                }

                // Check dropThing is last item that should not be dropped
                Thing dropThing = null;

                dropThing = backpack.SlotsComp.slots.First();

                if (dropThing == null)
                {
                    Log.Error(
                        toil.actor + " tried to drop null thing in "
                        + actor.jobs.curJob.GetTarget(StoreCellInd).Cell);
                    return;
                }

                IntVec3 destLoc = actor.jobs.curJob.GetTarget(StoreCellInd).Cell;
                Thing   dummy;

                if (destLoc.GetStorable(actor.Map) == null)
                {
                    actor.Map.designationManager.RemoveAllDesignationsOn(dropThing);
                    backpack.SlotsComp.slots.TryDrop(dropThing, destLoc, actor.Map, placeMode, out dummy);
                }
            };
            return(toil);
        }
        private float GetStatFactor(Pawn thisPawn)
        {
            float result = 1f;

            Apparel_Backpack  apparelBackpack   = ToolsForHaulUtility.TryGetBackpack(thisPawn);
            CompSlotsBackpack compSlotsBackpack = apparelBackpack?.SlotsComp;

            if (compSlotsBackpack != null)
            {
                result = Mathf.Clamp(compSlotsBackpack.MoveSpeedFactor - compSlotsBackpack.encumberPenalty, 0.5f, 1f);
            }

#if CR
            CompInventory compInventory = thisPawn.TryGetComp <CompInventory>();
            if (compInventory != null)
            {
                result = Mathf.Clamp(compInventory.moveSpeedFactor - compInventory.encumberPenalty, 0.1f, 1f);
                return(result);
            }
#endif
            return(result);
        }
Exemplo n.º 14
0
        public static Job HaulWithTools(Pawn pawn, Map map, Thing haulThing = null)
        {
            Trace.stopWatchStart();

            // Job Setting
            bool                useBackpack = false;
            JobDef              jobDef      = null;
            LocalTargetInfo     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;
                //             }
                //         }
                //     }
            }


            Job job = new Job(jobDef)
            {
                targetQueueA = new List <LocalTargetInfo>(),
                targetQueueB = new List <LocalTargetInfo>(),
                targetC      = targetC
            };

            if (useBackpack)
            {
                job.countQueue = 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;
                     *   }
                     * }
                     */
                    Thing           thing = remainingItems.ElementAt(i);
                    IntVec3         storageCell; //= FindStorageCell(pawn, remainingItems.ElementAt(i), map, job.targetQueueB);
                    StoragePriority currentPriority = HaulAIUtility.StoragePriorityAtFor(thing.Position, thing);
                    if (StoreUtility.TryFindBestBetterStoreCellFor(thing, pawn, pawn.Map, currentPriority, pawn.Faction, out storageCell))
                    {
                        job.targetQueueB.Add(storageCell);
                        break;
                    }
                }

                if (!job.targetQueueB.NullOrEmpty())
                {
                    Trace.AppendLine("Dropping Job is issued");
                    Trace.LogMessage();
                    return(job);
                }

                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
            {
                searchPos = pawn.Position;
            }

            foreach (SlotGroup slotGroup in map.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 =
                    map.listerHaulables.ThingsPotentiallyNeedingHauling()
                    .Count(item => slotGroup.Settings.AllowedToAccept(item));

                // Finding valid items
                Trace.AppendLine("Start Finding valid items");

                //ToDo TEST if this works without that line
                if (thingsCount > thresholdItem)
                {
                    Thing thing;
                    if (haulThing == null)
                    {
                        // ClosestThing_Global_Reachable Configuration
                        Predicate <Thing> predicate =
                            item =>
                            !job.targetQueueA.Contains(item) && !item.IsBurning() && !item.IsInAnyStorage() &&
                            (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)))) &&
                            slotGroup.Settings.AllowedToAccept(item) &&
                            HaulAIUtility.PawnCanAutomaticallyHaul(pawn, item, true);

                        // && !(item is UnfinishedThing && ((UnfinishedThing)item).BoundBill != null)
                        // && (item.def.IsNutritionSource && !SocialProperness.IsSociallyProper(item, pawn, false, false));
                        thing = GenClosest.ClosestThing_Global_Reachable(
                            searchPos,
                            map,
                            map.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, map, job.targetQueueB);
                    if (storageCell == IntVec3.Invalid)
                    {
                        break;
                    }

                    // Add Queue & Reserve
                    job.targetQueueA.Add(thing);

                    // for backpacks
                    if (useBackpack)
                    {
                        job.countQueue.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
                             map.listerHaulables.ThingsPotentiallyNeedingHauling()
                             .Where(
                                 item =>
                                 !job.targetQueueA.Contains(item) && !item.IsBurning() && !item.IsInAnyStorage() &&
                                 (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)))

                                  && slotGroup.Settings.AllowedToAccept(item) &&
                                  HaulAIUtility.PawnCanAutomaticallyHaul(pawn, item, true) &&
                                  center.DistanceToSquared(item.Position) <= ValidDistance)))
                    {
                        job.targetQueueA.Add(item);
                        if (useBackpack)
                        {
                            job.countQueue.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)
                    {
                        StoragePriority currentPriority = HaulAIUtility.StoragePriorityAtFor(thing.Position, thing);
                        IntVec3         storeCell;
                        if (
                            StoreUtility.TryFindBestBetterStoreCellFor(
                                thing,
                                pawn,
                                pawn.Map,
                                currentPriority,
                                pawn.Faction,
                                out storeCell))
                        {
                            job.targetQueueB.Add(storeCell);
                            if (job.targetQueueB.Count >= job.targetQueueA.Count)
                            {
                                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 (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);
        }
        protected override IEnumerable <Toil> MakeNewToils()
        {
            Apparel_Backpack backpack = this.CurJob.GetTarget(BackpackInd).Thing as Apparel_Backpack;

            ///
            // Set fail conditions
            ///
            // no free slots
            this.FailOn(() => backpack.SlotsComp.slots.Count >= backpack.MaxItem);

            //// hauling stuff not allowed
            // foreach (ThingCategoryDef category in CurJob.targetA.Thing.def.thingCategories)
            // {
            // this.FailOn(() => !backpack.slotsComp.Properties.allowedThingCategoryDefs.Contains(category));
            // this.FailOn(() => backpack.slotsComp.Properties.forbiddenSubThingCategoryDefs.Contains(category));
            // }


            ///
            // Define Toil
            ///

            Toil endOfJob = new Toil {
                initAction = () => { this.EndJobWith(JobCondition.Succeeded); }
            };
            Toil checkStoreCellEmpty = Toils_Jump.JumpIf(endOfJob, () => this.CurJob.GetTargetQueue(StoreCellInd).NullOrEmpty());
            Toil checkHaulableEmpty  = Toils_Jump.JumpIf(checkStoreCellEmpty, () => this.CurJob.GetTargetQueue(HaulableInd).NullOrEmpty());

            Toil checkBackpackEmpty = Toils_Jump.JumpIf(endOfJob, () => backpack.SlotsComp.slots.Count <= 0);

            ///
            // Toils Start
            ///

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

            yield return(Toils_Reserve.ReserveQueue(StoreCellInd));

            // JumpIf checkStoreCellEmpty
            yield return(checkHaulableEmpty);

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

                Toil gotoThing = Toils_Goto.GotoThing(HaulableInd, PathEndMode.ClosestTouch)
                                 .FailOnDestroyedOrNull(HaulableInd);
                yield return(gotoThing);

                // yield return Toils_Collect.CollectInBackpack(HaulableInd, backpack);
                Toil pickUpThingIntoSlot = new Toil
                {
                    initAction = () =>
                    {
                        if (!backpack.SlotsComp.slots.TryAdd(this.CurJob.targetA.Thing))
                        {
                            this.EndJobWith(JobCondition.Incompletable);
                        }
                    }
                };
                yield return(pickUpThingIntoSlot);

                yield return(Toils_Collect.CheckDuplicates(gotoThing, BackpackInd, HaulableInd));

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

            // JumpIf toilEnd
            yield return(checkStoreCellEmpty);

            {
                // Drop TargetQueue
                yield return(checkBackpackEmpty);

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

                Toil gotoCell = Toils_Goto.GotoCell(StoreCellInd, PathEndMode.ClosestTouch);
                yield return(gotoCell);

                yield return(Toils_Collect.DropTheCarriedFromBackpackInCell(StoreCellInd, ThingPlaceMode.Direct, backpack));

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

                yield return(Toils_Collect.CheckNeedStorageCell(gotoCell, BackpackInd, StoreCellInd));
            }

            yield return(endOfJob);
        }
Exemplo n.º 16
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);
        }