Exemple #1
0
        public static Job HopperFillFoodJob(Pawn pawn, ISlotGroupParent hopperSgp)
        {
            Building building = hopperSgp as Building;

            if (!pawn.CanReserveAndReach(building.Position, PathEndMode.Touch, pawn.NormalMaxDanger(), 1))
            {
                return(null);
            }
            ThingDef thingDef  = null;
            Thing    firstItem = building.Position.GetFirstItem();

            if (firstItem != null)
            {
                if (firstItem.def.IsNutritionSource)
                {
                    thingDef = firstItem.def;
                }
                else
                {
                    if (firstItem.IsForbidden(pawn.Faction))
                    {
                        return(null);
                    }
                    return(HaulAIUtility.HaulAsideJobFor(pawn, firstItem));
                }
            }
            List <Thing> list;

            if (thingDef == null)
            {
                list = Find.Map.listerThings.ThingsInGroup(ThingRequestGroup.FoodNotPlantOrTree);
            }
            else
            {
                list = Find.Map.listerThings.ThingsOfDef(thingDef);
            }
            for (int i = 0; i < list.Count; i++)
            {
                Thing thing = list[i];
                if (thing.def.ingestible.preferability == FoodPreferability.Raw)
                {
                    if (HaulAIUtility.PawnCanAutomaticallyHaul(pawn, thing))
                    {
                        if (Find.SlotGroupManager.SlotGroupAt(building.Position).Settings.AllowedToAccept(thing))
                        {
                            StoragePriority storagePriority = HaulAIUtility.StoragePriorityAtFor(thing.Position, thing);
                            if (storagePriority < hopperSgp.GetSlotGroup().Settings.Priority)
                            {
                                Job job = HaulAIUtility.HaulMaxNumToCellJob(pawn, thing, building.Position, true);
                                if (job != null)
                                {
                                    return(job);
                                }
                            }
                        }
                    }
                }
            }
            return(null);
        }
        private static bool AllowToolHaulUrgentlyJobOnThing_PreFix(ref Job __result, Pawn pawn, Thing t, bool forced = false)
        {
            if (ModCompatibilityCheck.AllowToolIsActive)
            {
                //allowTool HaulUrgently
                CompHauledToInventory takenToInventory = pawn.TryGetComp <CompHauledToInventory>();

                if (pawn.RaceProps.Humanlike &&
                    pawn.Faction == Faction.OfPlayer &&
                    t is Corpse == false &&
                    takenToInventory != null &&
                    !(t.def.defName.Contains("Chunk"))    //most of the time we don't have space for it
                    )
                {
                    StoragePriority currentPriority = HaulAIUtility.StoragePriorityAtFor(t.Position, t);
                    if (!StoreUtility.TryFindBestBetterStoreCellFor(t, pawn, pawn.Map, currentPriority, pawn.Faction, out IntVec3 storeCell, true))
                    {
                        JobFailReason.Is("NoEmptyPlaceLower".Translate());
                        return(false);
                    }

                    Job haul = new Job(PickUpAndHaulJobDefOf.HaulToInventory, t)
                    {
                        count = t.stackCount
                    };
                    __result = haul;
                    return(false);
                }
            }
            return(true);
        }
        protected override Job TryGiveJob(Pawn pawn)
        {
            Predicate <Thing> validator = delegate(Thing t)
            {
                if (t.IsForbidden(pawn))
                {
                    return(false);
                }
                if (!HaulAIUtility.PawnCanAutomaticallyHaulFast(pawn, t, false))
                {
                    return(false);
                }
                if (pawn.carryTracker.MaxStackSpaceEver(t.def) <= 0)
                {
                    return(false);
                }
                IntVec3 intVec = default(IntVec3);
                if (!StoreUtility.TryFindBestBetterStoreCellFor(t, pawn, pawn.Map, HaulAIUtility.StoragePriorityAtFor(t.Position, t), pawn.Faction, out intVec, true))
                {
                    return(false);
                }
                return(true);
            };
            Thing thing = GenClosest.ClosestThing_Global_Reachable(pawn.Position, pawn.Map, pawn.Map.listerHaulables.ThingsPotentiallyNeedingHauling(), PathEndMode.OnCell, TraverseParms.For(pawn, Danger.Deadly, TraverseMode.ByPawn, false), 9999f, validator, null);

            if (thing != null)
            {
                return(HaulAIUtility.HaulToStorageJob(pawn, thing));
            }
            return(null);
        }
Exemple #4
0
        public static Job SmartBuild(Pawn p, Job job)
        {
            if (p.story.WorkTagIsDisabled(WorkTags.Hauling))
            {
                return(job);
            }
            var carryCapacity   = p.GetStatValue(StatDefOf.CarryingCapacity);
            var itemCount       = job.count;
            var thing           = job.targetA.Thing;
            var storagePriority = HaulAIUtility.StoragePriorityAtFor(thing.Position, thing);


            IntVec3 storePos;

            if (StoreUtility.TryFindBestBetterStoreCellFor(thing, p, thing.Map, storagePriority, p.Faction, out storePos) && carryCapacity >= itemCount)
            {
                var targetPos = thing.Position;
                var destPos   = job.targetB.Thing.Position;
                if ((targetPos - destPos).LengthHorizontalSquared > (targetPos - storePos).LengthHorizontalSquared)
                {
                    return(HaulAIUtility.HaulMaxNumToCellJob(p, thing, storePos, false));
                }
            }

            return(job);
        }
Exemple #5
0
		public static Job HaulToStorageJob(Pawn p, Thing t)
		{
			var currentPriority = HaulAIUtility.StoragePriorityAtFor(t.Position, t);
			IntVec3 storeCell;
			if (!StoreUtility.TryFindBestBetterStoreCellFor(t, p, p.Map, currentPriority, p.Faction, out storeCell, true))
			{
				JobFailReason.Is(NoEmptyPlaceLowerTrans);
				return null;
			}
			return TestHaulMaxNumToCellJob(p, t, storeCell, false);
		}
Exemple #6
0
        private static bool IsPlaceToPutThing(Pawn p, Thing t)
        {
            StoragePriority currentPriority = HaulAIUtility.StoragePriorityAtFor(t.Position, t);
            IntVec3         storeCell;

            if (!StoreUtility.TryFindBestBetterStoreCellFor(t, p, p.Map, currentPriority, p.Faction, out storeCell))
            {
                return(false);
            }
            return(true);
        }
Exemple #7
0
        public static Job HopperFillFoodJob(Pawn pawn, ISlotGroupParent hopperSgp)
        {
            Building building = hopperSgp as Building;

            if (!pawn.CanReserveAndReach(building.Position, PathEndMode.Touch, pawn.NormalMaxDanger(), 1, -1, null, false))
            {
                return(null);
            }
            ThingDef thingDef  = null;
            Thing    firstItem = building.Position.GetFirstItem(building.Map);

            if (firstItem != null)
            {
                if (!Building_NutrientPasteDispenser.IsAcceptableFeedstock(firstItem.def))
                {
                    if (firstItem.IsForbidden(pawn))
                    {
                        return(null);
                    }
                    return(HaulAIUtility.HaulAsideJobFor(pawn, firstItem));
                }
                thingDef = firstItem.def;
            }
            List <Thing> list = (thingDef != null) ? pawn.Map.listerThings.ThingsOfDef(thingDef) : pawn.Map.listerThings.ThingsInGroup(ThingRequestGroup.FoodSourceNotPlantOrTree);
            bool         flag = false;

            for (int i = 0; i < list.Count; i++)
            {
                Thing thing = list[i];
                if (thing.def.IsNutritionGivingIngestible && (thing.def.ingestible.preferability == FoodPreferability.RawBad || thing.def.ingestible.preferability == FoodPreferability.RawTasty) && HaulAIUtility.PawnCanAutomaticallyHaul(pawn, thing, false) && pawn.Map.slotGroupManager.SlotGroupAt(building.Position).Settings.AllowedToAccept(thing))
                {
                    StoragePriority storagePriority = HaulAIUtility.StoragePriorityAtFor(thing.Position, thing);
                    if ((int)storagePriority >= (int)hopperSgp.GetSlotGroup().Settings.Priority)
                    {
                        flag = true;
                        JobFailReason.Is(WorkGiver_CookFillHopper.TheOnlyAvailableFoodIsInStorageOfHigherPriorityTrans);
                    }
                    else
                    {
                        Job job = HaulAIUtility.HaulMaxNumToCellJob(pawn, thing, building.Position, true);
                        if (job != null)
                        {
                            return(job);
                        }
                    }
                }
            }
            if (!flag)
            {
                JobFailReason.Is(WorkGiver_CookFillHopper.NoFoodToFillHopperTrans);
            }
            return(null);
        }
Exemple #8
0
        public static IntVec3 FindStorageCell(Pawn pawn, Thing haulable, Map map, List <LocalTargetInfo> targetQueue = null)
        {
            // Find closest cell in queue.
            if (!targetQueue.NullOrEmpty())
            {
                foreach (LocalTargetInfo target in targetQueue)
                {
                    foreach (IntVec3 adjCell in GenAdjFast.AdjacentCells8Way(target))
                    {
                        if (!targetQueue.Contains(adjCell) && adjCell.IsValidStorageFor(map, haulable))
                        {
                            if (pawn.CanReserveAndReach(adjCell, PathEndMode.ClosestTouch, Danger.Some))
                            {
                                return(adjCell);
                            }
                        }
                    }
                }
            }

            /*
             *          StoragePriority currentPriority = HaulAIUtility.StoragePriorityAtFor(closestHaulable.Position, closestHaulable);
             *          IntVec3 foundCell;
             *          if (StoreUtility.TryFindBestBetterStoreCellFor(closestHaulable, pawn, currentPriority, pawn.Faction, out foundCell, true))
             *              return foundCell;
             */
            // Vanilla code is not worked item on container.
            StoragePriority currentPriority = HaulAIUtility.StoragePriorityAtFor(haulable.Position, haulable);

            foreach (SlotGroup slotGroup in map.slotGroupManager.AllGroupsListInPriorityOrder)
            {
                if (slotGroup.Settings.Priority < currentPriority)
                {
                    break;
                }
                {
                    foreach (IntVec3 cell in slotGroup.CellsList)
                    {
                        if ((!targetQueue.NullOrEmpty() && !targetQueue.Contains(cell)) || targetQueue.NullOrEmpty())
                        {
                            if (cell.GetStorable(map) == null)
                            {
                                if (slotGroup.Settings.AllowedToAccept(haulable) && pawn.CanReserveAndReach(cell, PathEndMode.ClosestTouch, Danger.Deadly))
                                {
                                    return(cell);
                                }
                            }
                        }
                    }
                }
            }
            return(IntVec3.Invalid);
        }
Exemple #9
0
        //pick up stuff until you can't anymore,
        //while you're up and about, pick up something and haul it
        //before you go out, empty your pockets

        public override Job JobOnThing(Pawn pawn, Thing thing, bool forced = false)
        {
            CompHauledToInventory takenToInventory = pawn.TryGetComp <CompHauledToInventory>();

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

            if (thing is Corpse)
            {
                return(null);
            }

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

            if (thing.IsForbidden(pawn) || StoreUtility.IsInValidBestStorage(thing))
            {
                return(null);
            }

            //bulky gear (power armor + minigun) so don't bother.
            if (MassUtility.GearMass(pawn) / MassUtility.Capacity(pawn) >= 0.8f)
            {
                return(null);
            }

            StoragePriority currentPriority = HaulAIUtility.StoragePriorityAtFor(thing.Position, thing);

            if (StoreUtility.TryFindBestBetterStoreCellFor(thing, pawn, pawn.Map, currentPriority, pawn.Faction, out IntVec3 storeCell, true))
            {
                //since we've gone through all the effort of getting the loc, might as well use it.
                //Don't multi-haul food to hoppers.
                if (thing.def.IsNutritionGivingIngestible)
                {
                    if (thing.def.ingestible.preferability == FoodPreferability.RawBad || thing.def.ingestible.preferability == FoodPreferability.RawTasty)
                    {
                        List <Thing> thingList = storeCell.GetThingList(thing.Map);
                        for (int i = 0; i < thingList.Count; i++)
                        {
                            Thing thingAtCell = thingList[i];
                            if (thingAtCell.def == ThingDefOf.Hopper)
                            {
                                return(HaulAIUtility.HaulToStorageJob(pawn, thing));
                            }
                        }
                    }
                }
            }
        // duplicated to make changes
        public Job HaulToStorageJob(Pawn p, Thing t)
        {
            StoragePriority currentPriority = HaulAIUtility.StoragePriorityAtFor(t.Position, t);
            IntVec3         storeCell;

            // call duplicated to make changes
            if (!TryFindBestBetterStoreCellFor(t, p, currentPriority, p.Faction, out storeCell, true))
            {
                JobFailReason.Is("NoEmptyPlace");
                return(null);
            }
            // call duplicated to make changes

            return(HaulMaxNumToCellJob(p, t, storeCell, false));
        }
Exemple #11
0
        private static Job                  HopperFillJob(Pawn pawn, ISlotGroupParent hopperSgp, Thing resource)
        {
            Building building = hopperSgp as Building;

            // Get a sorted list (by distance) of matching resources
            List <Thing> resources = null;

            if (resource != null)
            {
                resources = Find.Map.listerThings.ThingsOfDef(resource.def)
                            .Where(t => (
                                       (HaulAIUtility.PawnCanAutomaticallyHaul(pawn, t)) &&
                                       (hopperSgp.GetStoreSettings().AllowedToAccept(t)) &&
                                       (HaulAIUtility.StoragePriorityAtFor(t.Position, t) < hopperSgp.GetSlotGroup().Settings.Priority)
                                       )).ToList();
            }
            else
            {
                resources = Find.Map.listerThings.AllThings
                            .Where(t => (
                                       (HaulAIUtility.PawnCanAutomaticallyHaul(pawn, t)) &&
                                       (hopperSgp.GetStoreSettings().AllowedToAccept(t)) &&
                                       (HaulAIUtility.StoragePriorityAtFor(t.Position, t) < hopperSgp.GetSlotGroup().Settings.Priority)
                                       )).ToList();
            }

            if (resources.NullOrEmpty())
            {
                return((Job)null);
            }

            // Sort by distance (closest first)
            resources.Sort((Thing x, Thing y) => (Gen.ManhattanDistanceFlat(x.Position, building.Position) < Gen.ManhattanDistanceFlat(y.Position, building.Position)) ? -1 : 1);

            var grabResource = resources.First();

            if (grabResource != null)
            {
                // Try to haul the first (closest) resource found
                var job = HaulAIUtility.HaulMaxNumToCellJob(pawn, grabResource, building.Position, true);
                if (job != null)
                {
                    return(job);
                }
            }
            return((Job)null);
        }
Exemple #12
0
        bool TestStoreInColderPlace(Pawn p, Thing t, out IntVec3 storeCell)
        {
            storeCell = IntVec3.Invalid;
            Map             map                    = p.Map;
            StoragePriority currentPriority        = HaulAIUtility.StoragePriorityAtFor(t.Position, t);
            bool            isThereBetterStoreCell = ModdedStoreUtil.TryFindBestBetterStoreCellFor(t, p, map,
                                                                                                   currentPriority,
                                                                                                   p.Faction, out IntVec3 searchCell,
                                                                                                   true, true, true);

            if (!isThereBetterStoreCell)
            {
                return(false);
            }

            storeCell = searchCell;
            return(true);
        }
Exemple #13
0
        protected override IEnumerable <Toil> MakeNewToils()
        {
            this.FailOnDespawnedNullOrForbidden(TargetIndex.A);
            this.FailOnBurningImmobile(TargetIndex.A);
            yield return(Toils_Goto.GotoThing(TargetIndex.A, PathEndMode.Touch));

            yield return(Toils_General.Wait(200).FailOnDestroyedNullOrForbidden(TargetIndex.A).FailOnCannotTouch(TargetIndex.A, PathEndMode.Touch).FailOn(() => !this.$this.Barrel.Fermented).WithProgressBarToilDelay(TargetIndex.A, false, -0.5f));

            yield return(new Toil
            {
                initAction = delegate
                {
                    Thing thing = this.$this.Barrel.TakeOutBeer();
                    GenPlace.TryPlaceThing(thing, this.$this.pawn.Position, this.$this.Map, ThingPlaceMode.Near, null);
                    StoragePriority currentPriority = HaulAIUtility.StoragePriorityAtFor(thing.Position, thing);
                    IntVec3 c;
                    if (StoreUtility.TryFindBestBetterStoreCellFor(thing, this.$this.pawn, this.$this.Map, currentPriority, this.$this.pawn.Faction, out c, true))
                    {
                        this.$this.job.SetTarget(TargetIndex.C, c);
                        this.$this.job.SetTarget(TargetIndex.B, thing);
                        this.$this.job.count = thing.stackCount;
                    }
                    else
                    {
                        this.$this.EndJobWith(JobCondition.Incompletable);
                    }
                },
                defaultCompleteMode = ToilCompleteMode.Instant
            });

            yield return(Toils_Reserve.Reserve(TargetIndex.B, 1, -1, null));

            yield return(Toils_Reserve.Reserve(TargetIndex.C, 1, -1, null));

            yield return(Toils_Goto.GotoThing(TargetIndex.B, PathEndMode.ClosestTouch));

            yield return(Toils_Haul.StartCarryThing(TargetIndex.B, false, false, false));

            Toil carryToCell = Toils_Haul.CarryHauledThingToCell(TargetIndex.C);

            yield return(carryToCell);

            yield return(Toils_Haul.PlaceHauledThingInCell(TargetIndex.C, carryToCell, true));
        }
        protected override IEnumerable <Toil> MakeNewToils()
        {
            // Verify processor validity
            this.FailOnDespawnedNullOrForbidden(ProcessorInd);
            this.FailOn(() => !Processor.Finished);

            // Go to the processor
            yield return(Toils_Goto.GotoThing(ProcessorInd, PathEndMode.ClosestTouch));

            // Add delay for collecting items from the processor
            yield return(Toils_General.Wait(Static.GenericWaitDuration)
                         .FailOnDestroyedNullOrForbidden(ProcessorInd)
                         .WithProgressBarToilDelay(ProcessorInd));

            // Collect items
            yield return(new Toil()
            {
                initAction = () => {
                    Thing item = Processor.TakeOutProduct();
                    GenPlace.TryPlaceThing(item, pawn.Position, Map, ThingPlaceMode.Near);
                    StoragePriority storagePriority = HaulAIUtility.StoragePriorityAtFor(item.Position, item);

                    // Try to find a suitable storage spot for the item
                    if (StoreUtility.TryFindBestBetterStoreCellFor(item, pawn, Map, storagePriority, pawn.Faction, out IntVec3 c))
                    {
                        job.SetTarget(TargetIndex.C, c);
                        job.SetTarget(TargetIndex.B, item);
                        job.count = item.stackCount;
                    }
                    // If there is no spot to store the item, end this job
                    else
                    {
                        EndJobWith(JobCondition.Incompletable);
                    }
                },
                defaultCompleteMode = ToilCompleteMode.Instant
            });
        public override Job JobOnThing(Pawn pawn, Thing t)
        {
            if (!(t is Corpse))
            {
                return(null);
            }
            Area outpostArea = OG_Util.FindOutpostArea();

            if ((outpostArea != null) &&
                (outpostArea.ActiveCells.Contains(t.Position)))
            {
                // Get potential storage cell and check it is in the outpost area.
                StoragePriority currentPriority = HaulAIUtility.StoragePriorityAtFor(t.Position, t);
                IntVec3         storeCell;
                if (StoreUtility.TryFindBestBetterStoreCellFor(t, pawn, currentPriority, pawn.Faction, out storeCell, true))
                {
                    if (outpostArea.ActiveCells.Contains(storeCell))
                    {
                        return(base.JobOnThing(pawn, t));
                    }
                }
            }
            return(null);
        }
        //regular Toils_Haul.CheckForGetOpportunityDuplicate isn't going to work for our purposes, since we're not carrying anything.
        //Carrying something yields weird results with unspawning errors when transfering to inventory, so we copy-past-- I mean, implement our own.
        public Toil CheckForOtherItemsToHaulToInventory(Toil getHaulTargetToil, TargetIndex haulableInd, float distanceToOthers, Predicate <Thing> extraValidator = null)
        {
            Toil toil = new Toil();

            toil.initAction = delegate
            {
                Pawn    actor     = toil.actor;
                Job     curJob    = actor.jobs.curJob;
                IntVec3 storeCell = IntVec3.Invalid;

                Predicate <Thing> validator = (Thing t) => t.Spawned &&
                                              HaulAIUtility.PawnCanAutomaticallyHaulFast(actor, t, false) &&
                                              (!t.IsInValidBestStorage()) &&
                                              !t.IsForbidden(actor) &&
                                              !(t is Corpse) &&
                                              (StoreUtility.TryFindBestBetterStoreCellFor(t, pawn, pawn.Map, (HaulAIUtility.StoragePriorityAtFor(t.Position, t)), actor.Faction, out storeCell, true)) &&
                                              (extraValidator == null || extraValidator(t)) &&
                                              actor.CanReserve(t, 1, -1, null, false);

                Thing thing = GenClosest.ClosestThingReachable(actor.Position, actor.Map, ThingRequest.ForGroup(ThingRequestGroup.HaulableAlways), PathEndMode.ClosestTouch,
                                                               TraverseParms.For(actor, Danger.Deadly, TraverseMode.ByPawn, false), Math.Max(distanceToOthers, 12f), validator, null, 0, -1, false, RegionType.Set_Passable, false);

                float usedBulkByPct   = 1f;
                float usedWeightByPct = 1f;

                try
                {
                    ((Action)(() =>
                    {
                        if (ModCompatibilityCheck.CombatExtendedIsActive)
                        {
                            CombatExtended.CompInventory ceCompInventory = actor.GetComp <CombatExtended.CompInventory>();
                            usedWeightByPct = ceCompInventory.currentWeight / ceCompInventory.capacityWeight;
                            usedBulkByPct = ceCompInventory.currentBulk / ceCompInventory.capacityBulk;
                        }
                    }))();
                }
                catch (TypeLoadException) { }


                if (thing != null && (MassUtility.EncumbrancePercent(actor) <= 0.9f || usedBulkByPct >= 0.7f || usedWeightByPct >= 0.8f))
                {
                    curJob.SetTarget(haulableInd, thing);
                    actor.Reserve(storeCell, this.job, 1, -1, null);
                    actor.jobs.curDriver.JumpToToil(getHaulTargetToil);
                    return;
                }
                if (thing != null)
                {
                    Job haul = HaulAIUtility.HaulToStorageJob(actor, thing);
                    if (haul?.TryMakePreToilReservations(actor) ?? false)
                    {
                        actor.jobs.jobQueue.EnqueueFirst(haul, new JobTag?(JobTag.Misc));
                        this.EndJobWith(JobCondition.Succeeded);
                    }
                }
                if (thing == null)
                {
                    Job job = new Job(PickUpAndHaulJobDefOf.UnloadYourHauledInventory);
                    if (job.TryMakePreToilReservations(actor))
                    {
                        actor.jobs.jobQueue.EnqueueFirst(job, new JobTag?(JobTag.Misc));
                        this.EndJobWith(JobCondition.Succeeded);
                    }
                }
            };
            return(toil);
        }
Exemple #17
0
        /// <summary>
        /// Find spot, reserve spot, pull thing out of inventory, go to spot, drop stuff, repeat.
        /// </summary>
        /// <returns></returns>
        protected override IEnumerable <Toil> MakeNewToils()
        {
            CompHauledToInventory takenToInventory = pawn.TryGetComp <CompHauledToInventory>();
            HashSet <Thing>       carriedThing     = takenToInventory.GetHashSet();

            if (ModCompatibilityCheck.ExtendedStorageIsActive)
            {
                //ES takes at least ~10 ticks to move from the feeder to the stockpile, so workaround ahoy
                UnloadDuration = 20;
            }

            Toil wait      = Toils_General.Wait(UnloadDuration);
            Toil celebrate = Toils_General.Wait(UnloadDuration);

            yield return(wait);

            Toil findSpot = new Toil
            {
                initAction = () =>
                {
                    ThingStackPart unloadableThing = FirstUnloadableThing(pawn);

                    if (unloadableThing.Count == 0 && carriedThing.Count == 0)
                    {
                        this.EndJobWith(JobCondition.Succeeded);
                    }

                    if (unloadableThing.Count != 0)
                    {
                        StoragePriority currentPriority = HaulAIUtility.StoragePriorityAtFor(pawn.Position, unloadableThing.Thing);
                        if (!StoreUtility.TryFindStoreCellNearColonyDesperate(unloadableThing.Thing, this.pawn, out IntVec3 c))
                        {
                            this.pawn.inventory.innerContainer.TryDrop(unloadableThing.Thing, ThingPlaceMode.Near, unloadableThing.Thing.stackCount, out Thing thing, null);
                            this.EndJobWith(JobCondition.Succeeded);
                        }
                        else
                        {
                            this.job.SetTarget(TargetIndex.A, unloadableThing.Thing);
                            this.job.SetTarget(TargetIndex.B, c);
                            this.countToDrop = unloadableThing.Thing.stackCount;
                        }
                    }
                }
            };

            yield return(findSpot);

            yield return(Toils_Reserve.Reserve(TargetIndex.B, 1, -1, null));

            yield return(new Toil
            {
                initAction = delegate
                {
                    Thing thing = this.job.GetTarget(TargetIndex.A).Thing;
                    if (thing == null || !this.pawn.inventory.innerContainer.Contains(thing))
                    {
                        carriedThing.Remove(thing);
                        pawn.jobs.curDriver.JumpToToil(wait);
                        return;
                    }
                    if (!this.pawn.health.capacities.CapableOf(PawnCapacityDefOf.Manipulation) || !thing.def.EverStoreable)
                    {
                        this.pawn.inventory.innerContainer.TryDrop(thing, ThingPlaceMode.Near, this.countToDrop, out thing, null);
                        this.EndJobWith(JobCondition.Succeeded);
                        carriedThing.Remove(thing);
                    }
                    else
                    {
                        this.pawn.inventory.innerContainer.TryTransferToContainer(thing, this.pawn.carryTracker.innerContainer, this.countToDrop, out thing, true);
                        this.job.count = this.countToDrop;
                        this.job.SetTarget(TargetIndex.A, thing);
                        carriedThing.Remove(thing);
                    }
                    try
                    {
                        ((Action)(() =>
                        {
                            if (ModCompatibilityCheck.CombatExtendedIsActive)
                            {
                                CombatExtended.CompInventory ceCompInventory = pawn.GetComp <CombatExtended.CompInventory>();
                                ceCompInventory.UpdateInventory();
                            }
                        }))();
                    }
                    catch (TypeLoadException) { }
                    thing.SetForbidden(false, false);
                }
            });

            Toil carryToCell = Toils_Haul.CarryHauledThingToCell(TargetIndex.B);

            yield return(Toils_Goto.GotoCell(TargetIndex.B, PathEndMode.Touch));

            yield return(carryToCell);

            yield return(Toils_Haul.PlaceHauledThingInCell(TargetIndex.B, carryToCell, true));

            //If the original cell is full, PlaceHauledThingInCell will set a different TargetIndex resulting in errors on yield return Toils_Reserve.Release.
            //We still gotta release though, mostly because of Extended Storage.
            Toil releaseReservation = new Toil
            {
                initAction = () =>
                {
                    if (pawn.Map.reservationManager.ReservedBy(this.job.targetB, pawn, pawn.CurJob) && !ModCompatibilityCheck.HCSKIsActive)
                    {
                        pawn.Map.reservationManager.Release(this.job.targetB, pawn, pawn.CurJob);
                    }
                }
            };

            yield return(releaseReservation);

            yield return(Toils_Jump.Jump(wait));

            yield return(celebrate);
        }
Exemple #18
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);
        }
        private Toil Collect()
        {
            Toil toil = new Toil();

            toil.initAction = delegate {
                // Increment the record for how many cells this pawn has mined since this counts as mining
                pawn.records.Increment(RecordDefOf.CellsMined);

                // Start with None to act as a fallback. Rubble will be returned with this parameter
                ResourceRequest req = ResourceRequest.None;

                // Use the mineModeToggle to determine the request
                req = (Quarry.mineModeToggle ? ResourceRequest.Resources : ResourceRequest.Blocks);

                MoteType mote           = MoteType.None;
                bool     singleSpawn    = true;
                bool     eventTriggered = false;
                int      stackCount     = 1;

                // Get the resource from the quarry
                ThingDef def = Quarry.GiveResources(req, out mote, out singleSpawn, out eventTriggered);

                // If something went wrong, bail out
                if (def == null || def.thingClass == null)
                {
                    Log.Warning("Quarry:: Tried to quarry mineable ore, but the ore given was null.");
                    mote        = MoteType.None;
                    singleSpawn = true;
                    // This shouldn't happen at all, but if it does let's add a little reward instead of just giving rubble
                    def = ThingDefOf.ChunkSlagSteel;
                }

                Thing haulableResult = ThingMaker.MakeThing(def);
                if (!singleSpawn && def != ThingDefOf.Component)
                {
                    int sub = (int)(def.BaseMarketValue / 3f);
                    if (sub >= 10)
                    {
                        sub = 9;
                    }

                    stackCount += Mathf.Min(Rand.RangeInclusive(15 - sub, 40 - (sub * 2)), def.stackLimit - 1);
                }

                if (def == ThingDefOf.Component)
                {
                    stackCount += Random.Range(0, 1);
                }

                haulableResult.stackCount = stackCount;

                if (stackCount >= 30)
                {
                    mote = MoteType.LargeVein;
                }

                // Place the resource near the pawn
                GenPlace.TryPlaceThing(haulableResult, pawn.Position, Map, ThingPlaceMode.Near);

                // If the resource had a mote, throw it
                if (mote == MoteType.LargeVein)
                {
                    MoteMaker.ThrowText(haulableResult.DrawPos, Map, Static.TextMote_LargeVein, Color.green, 3f);
                }
                else if (mote == MoteType.Failure)
                {
                    MoteMaker.ThrowText(haulableResult.DrawPos, Map, Static.TextMote_MiningFailed, Color.red, 3f);
                }

                // If the sinkhole event was triggered, damage the pawn and end this job
                // Even if the sinkhole doesn't incapacitate the pawn, they will probably want to seek medical attention
                if (eventTriggered)
                {
                    Messages.Message("QRY_MessageSinkhole".Translate(pawn.NameStringShort), pawn, MessageTypeDefOf.ThreatSmall);
                    DamageInfo dInfo = new DamageInfo(DamageDefOf.Crush, 9, -1f, category: DamageInfo.SourceCategory.Collapse);
                    dInfo.SetBodyRegion(BodyPartHeight.Bottom, BodyPartDepth.Inside);
                    pawn.TakeDamage(dInfo);
                    pawn.TakeDamage(dInfo);

                    EndJobWith(JobCondition.Succeeded);
                }

                // Prevent the colonists from trying to haul rubble, which just makes them visit the platform
                if (haulableResult.def == ThingDefOf.RockRubble)
                {
                    EndJobWith(JobCondition.Succeeded);
                }

                // If this is a chunk or slag, mark it as haulable if allowed to
                if (haulableResult.def.designateHaulable && Quarry.autoHaul)
                {
                    Map.designationManager.AddDesignation(new Designation(haulableResult, DesignationDefOf.Haul));
                }

                // Setup IntVec for assigning
                IntVec3 c;

                // Try to find a suitable storage spot for the resource, removing it from the quarry
                // If there are no platforms with free space, try to haul it to a storage area
                if (Quarry.autoHaul)
                {
                    if (Quarry.HasConnectedPlatform && Quarry.TryFindBestStoreCellFor(haulableResult, pawn, Map, pawn.Faction, out c))
                    {
                        job.SetTarget(TargetIndex.B, haulableResult);
                        job.count = haulableResult.stackCount;
                        job.SetTarget(TargetIndex.C, c);
                    }
                    else
                    {
                        StoragePriority currentPriority = HaulAIUtility.StoragePriorityAtFor(haulableResult.Position, haulableResult);
                        if (StoreUtility.TryFindBestBetterStoreCellFor(haulableResult, pawn, Map, currentPriority, pawn.Faction, out c))
                        {
                            job.SetTarget(TargetIndex.B, haulableResult);
                            job.count = haulableResult.stackCount;
                            job.SetTarget(TargetIndex.C, c);
                        }
                    }
                }
                // If there is no spot to store the resource, end this job
                else
                {
                    EndJobWith(JobCondition.Succeeded);
                }
            };
            toil.defaultCompleteMode = ToilCompleteMode.Instant;

            return(toil);
        }
        protected override IEnumerable <Toil> MakeNewToils()
        {
            CompUniversalFermenter comp = Fermenter.TryGetComp <CompUniversalFermenter>();

            // Verify fermenter validity
            this.FailOn(() => !comp.Fermented);
            this.FailOnDestroyedNullOrForbidden(FermenterInd);

            // Reserve fermenter
            yield return(Toils_Reserve.Reserve(FermenterInd));

            // Go to the fermenter
            yield return(Toils_Goto.GotoThing(FermenterInd, PathEndMode.ClosestTouch));

            // Add delay for collecting product from fermenter, if it is ready
            yield return(Toils_General.Wait(Duration).FailOnDestroyedNullOrForbidden(FermenterInd).WithProgressBarToilDelay(FermenterInd));

            // Collect product
            Toil collect = new Toil();

            collect.initAction = () =>
            {
                Thing product = comp.TakeOutProduct();
                GenPlace.TryPlaceThing(product, pawn.Position, Map, ThingPlaceMode.Near);
                StoragePriority storagePriority = HaulAIUtility.StoragePriorityAtFor(product.Position, product);
                IntVec3         c;

                // Try to find a suitable storage spot for the product
                if (StoreUtility.TryFindBestBetterStoreCellFor(product, pawn, Map, storagePriority, pawn.Faction, out c))
                {
                    this.job.SetTarget(TargetIndex.B, product);
                    this.job.count = product.stackCount;
                    this.job.SetTarget(TargetIndex.C, c);
                }
                // If there is no spot to store the product, end this job
                else
                {
                    EndJobWith(JobCondition.Incompletable);
                }
            };
            collect.defaultCompleteMode = ToilCompleteMode.Instant;
            yield return(collect);

            // Reserve the product
            yield return(Toils_Reserve.Reserve(ProductToHaulInd));

            // Reserve the storage cell
            yield return(Toils_Reserve.Reserve(StorageCellInd));

            // Go to the product
            yield return(Toils_Goto.GotoThing(ProductToHaulInd, PathEndMode.ClosestTouch));

            // Pick up the product
            yield return(Toils_Haul.StartCarryThing(ProductToHaulInd));

            // Carry the product to the storage cell, then place it down
            Toil carry = Toils_Haul.CarryHauledThingToCell(StorageCellInd);

            yield return(carry);

            yield return(Toils_Haul.PlaceHauledThingInCell(StorageCellInd, carry, true));

            // End the current job
            yield break;
        }
Exemple #21
0
        protected override IEnumerable <Toil> MakeNewToils()
        {
            this.FailOnDestroyedOrNull(TargetIndex.A);
            yield return(new Toil
            {
                initAction = delegate
                {
                    this.$this.pawn.pather.StopDead();
                },
                defaultCompleteMode = ToilCompleteMode.Delay,
                defaultDuration = 60
            });

            yield return(new Toil
            {
                initAction = delegate
                {
                    if (this.$this.pawn.apparel.WornApparel.Contains(this.$this.TargetApparel))
                    {
                        Apparel apparel;
                        if (this.$this.pawn.apparel.TryDrop(this.$this.TargetApparel, out apparel))
                        {
                            this.$this.job.targetA = apparel;
                            if (this.$this.job.haulDroppedApparel)
                            {
                                apparel.SetForbidden(false, false);
                                StoragePriority currentPriority = HaulAIUtility.StoragePriorityAtFor(apparel.Position, apparel);
                                IntVec3 c;
                                if (StoreUtility.TryFindBestBetterStoreCellFor(apparel, this.$this.pawn, this.$this.Map, currentPriority, this.$this.pawn.Faction, out c, true))
                                {
                                    this.$this.job.count = apparel.stackCount;
                                    this.$this.job.targetB = c;
                                }
                                else
                                {
                                    this.$this.EndJobWith(JobCondition.Incompletable);
                                }
                            }
                            else
                            {
                                this.$this.EndJobWith(JobCondition.Succeeded);
                            }
                        }
                        else
                        {
                            this.$this.EndJobWith(JobCondition.Incompletable);
                        }
                    }
                    else
                    {
                        this.$this.EndJobWith(JobCondition.Incompletable);
                    }
                }
            });

            if (this.job.haulDroppedApparel)
            {
                yield return(Toils_Reserve.Reserve(TargetIndex.B, 1, -1, null));

                yield return(Toils_Reserve.Reserve(TargetIndex.A, 1, -1, null));

                yield return(Toils_Haul.StartCarryThing(TargetIndex.A, false, false, false).FailOn(() => !this.$this.pawn.health.capacities.CapableOf(PawnCapacityDefOf.Manipulation)));

                Toil carryToCell = Toils_Haul.CarryHauledThingToCell(TargetIndex.B);
                yield return(carryToCell);

                yield return(Toils_Haul.PlaceHauledThingInCell(TargetIndex.B, carryToCell, true));
            }
        }
Exemple #22
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);
        }
Exemple #23
0
        internal static Job HopperFillFoodJob(Pawn pawn, Building hopper, Thing parent)
        {
            var hopperSgp = hopper as ISlotGroupParent;

            if (
                (!pawn.CanReserveAndReach(
                     hopper.Position,
                     PathEndMode.Touch,
                     pawn.NormalMaxDanger(),
                     1)
                )
                )
            {
                return(null);
            }
            ThingDef resourceDef = null;
            var      firstItem   = hopper.Position.GetFirstItem();

            if (firstItem != null)
            {
                if (
                    (
                        (parent is Building_NutrientPasteDispenser) &&
                        (Building_NutrientPasteDispenser.IsAcceptableFeedstock(firstItem.def))
                    ) ||
                    (
                        (parent is Building_AutomatedFactory) &&
                        (((Building_AutomatedFactory)parent).CompHopperUser.ResourceSettings.AllowedToAccept(firstItem))
                    )
                    )
                {
                    resourceDef = firstItem.def;
                }
                else
                {
                    if (firstItem.IsForbidden(pawn))
                    {
                        return(( Job )null);
                    }
                    return(HaulAIUtility.HaulAsideJobFor(pawn, firstItem));
                }
            }
            List <Thing> list =
                resourceDef != null
                ? Find.Map.listerThings.ThingsOfDef(resourceDef)
                : Find.Map.listerThings.ThingsInGroup(ThingRequestGroup.FoodSourceNotPlantOrTree);

            for (int index = 0; index < list.Count; ++index)
            {
                Thing t = list[index];
                if (
                    (t.def.IsNutritionGivingIngestible) &&
                    (
                        (t.def.ingestible.preferability == FoodPreferability.RawBad) ||
                        (t.def.ingestible.preferability == FoodPreferability.RawTasty)
                    ) &&
                    (HaulAIUtility.PawnCanAutomaticallyHaul(pawn, t)) &&
                    (
                        (Find.SlotGroupManager.SlotGroupAt(hopper.Position).Settings.AllowedToAccept(t)) &&
                        (HaulAIUtility.StoragePriorityAtFor(t.Position, t) < hopperSgp.GetSlotGroup().Settings.Priority)
                    )
                    )
                {
                    Job job = HaulAIUtility.HaulMaxNumToCellJob(pawn, t, hopper.Position, true);
                    if (job != null)
                    {
                        return(job);
                    }
                }
            }
            return(null);
        }