Пример #1
0
        public static void CheckIfPawnShouldUnloadInventory(Pawn pawn, bool forced = false)
        {
            Job job = JobMaker.MakeJob(PickUpAndHaulJobDefOf.UnloadYourHauledInventory, pawn);
            CompHauledToInventory itemsTakenToInventory = pawn.TryGetComp <CompHauledToInventory>();

            if (itemsTakenToInventory == null)
            {
                return;
            }

            HashSet <Thing> carriedThing = itemsTakenToInventory.GetHashSet();

            if (pawn.Faction != Faction.OfPlayer || !pawn.RaceProps.Humanlike)
            {
                return;
            }
            if (carriedThing == null || carriedThing.Count == 0 || pawn.inventory.innerContainer.Count == 0)
            {
                return;
            }

            if (forced)
            {
                if (job.TryMakePreToilReservations(pawn, false))
                {
                    pawn.jobs.jobQueue.EnqueueFirst(job, JobTag.Misc);
                    return;
                }
            }

            if (MassUtility.EncumbrancePercent(pawn) >= 0.90f || carriedThing.Count >= 1)
            {
                if (job.TryMakePreToilReservations(pawn, false))
                {
                    pawn.jobs.jobQueue.EnqueueFirst(job, JobTag.Misc);
                    return;
                }
            }

            if (pawn.inventory.innerContainer?.Count >= 1)
            {
                foreach (Thing rottable in pawn.inventory.innerContainer)
                {
                    CompRottable compRottable = rottable.TryGetComp <CompRottable>();

                    if (compRottable?.TicksUntilRotAtCurrentTemp < 30000)
                    {
                        pawn.jobs.jobQueue.EnqueueFirst(job, JobTag.Misc);
                        return;
                    }
                }
            }

            if (Find.TickManager.TicksGame % 50 == 0 && pawn.inventory.innerContainer.Count < carriedThing.Count)
            {
                Verse.Log.Warning("[PickUpAndHaul] " + pawn + " inventory was found out of sync with haul index. Pawn will drop their inventory.");
                carriedThing.Clear();
                pawn.inventory.UnloadEverything = true;
            }
        }
        /// <summary>
        /// the workgiver checks for encumbered, this is purely extra for CE
        /// </summary>
        /// <returns></returns>
        public Toil CheckForOverencumberedForCombatExtended()
        {
            Toil toil = new Toil();

            if (!ModCompatibilityCheck.CombatExtendedIsActive)
            {
                return(toil);
            }

            toil.initAction = delegate
            {
                Pawn  actor     = toil.actor;
                Job   curJob    = actor.jobs.curJob;
                Thing nextThing = curJob.targetA.Thing;

                var ceOverweight = CompatHelper.CeOverweight(pawn);

                if (!(MassUtility.EncumbrancePercent(actor) <= 0.9f && !ceOverweight))
                {
                    Job haul = HaulAIUtility.HaulToStorageJob(actor, nextThing);
                    if (haul?.TryMakePreToilReservations(actor, false) ?? false)
                    {
                        //note that HaulToStorageJob etc doesn't do opportunistic duplicate hauling for items in valid storage. REEEE
                        actor.jobs.jobQueue.EnqueueFirst(haul, JobTag.Misc);
                        EndJobWith(JobCondition.Succeeded);
                    }
                }
            };

            return(toil);
        }
        public Toil CheckForOverencumbered()
        {
            Toil toil = new Toil();

            toil.initAction = delegate
            {
                Pawn  actor     = toil.actor;
                Job   curJob    = actor.jobs.curJob;
                Thing nextThing = curJob.targetA.Thing;

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

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


                if (!(MassUtility.EncumbrancePercent(actor) <= 0.9f /*|| usedBulkByPct >= 0.7f || usedWeightByPct >= 0.8f*/))
                {
                    Job haul = HaulAIUtility.HaulToStorageJob(actor, nextThing);
                    if (haul?.TryMakePreToilReservations(actor, false) ?? false)
                    {
                        //note that HaulToStorageJob etc doesn't do opportunistic duplicate hauling for items in valid storage. REEEE
                        actor.jobs.jobQueue.EnqueueFirst(haul, JobTag.Misc);
                        EndJobWith(JobCondition.Succeeded);
                    }
                }
            };
            return(toil);
        }
        //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);
        }