public static Thing TryGetBackpackLastItem(Pawn pawn) { Apparel_Backpack backpack = ToolsForHaulUtility.TryGetBackpack(pawn); if (backpack == null) { return(null); } Thing lastItem = null; int lastItemInd = -1; Thing foodInInventory = FoodUtility.BestFoodInInventory(pawn); if (pawn.inventory.container.Count > 0) { if (backpack.numOfSavedItems > 0) { lastItemInd = ((backpack.numOfSavedItems >= pawn.inventory.container.Count)?pawn.inventory.container.Count : backpack.numOfSavedItems) - 1; lastItem = pawn.inventory.container[lastItemInd]; } if (foodInInventory != null && backpack.numOfSavedItems < pawn.inventory.container.Count && pawn.inventory.container[lastItemInd + 1] == foodInInventory) { lastItem = foodInInventory; } } return(lastItem); }
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 : actor.inventory.container.Count) + targetQueue.Count; int curItemStack = (cart != null ? cart.storage.TotalStackCount : actor.inventory.container.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 && !FireUtility.IsBurning(item) && 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; } }; return(toil); }
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 : actor.inventory.container; 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); }
protected override IEnumerable <Toil> MakeNewToils() { Apparel_Backpack backpack = CurJob.GetTarget(BackpackInd).Thing as Apparel_Backpack; /// //Set fail conditions /// //Backpack is full. this.FailOn(() => { return((pawn.inventory.container.Count < backpack.MaxItem) ? false : true); }); /// //Define Toil /// Toil extractB = new Toil(); extractB.initAction = () => { if (!CurJob.targetQueueB.NullOrEmpty()) { CurJob.targetB = CurJob.targetQueueB.First(); CurJob.targetQueueB.RemoveAt(0); this.FailOnDestroyedOrNull(HaulableInd); } else { this.EndJobWith(JobCondition.Succeeded); } }; Toil toilGoToThing = Toils_Goto.GotoThing(HaulableInd, PathEndMode.ClosestTouch) .FailOnDestroyedOrNull(HaulableInd); /// //Toils Start /// //Reserve thing to be stored and storage cell yield return(Toils_Reserve.Reserve(BackpackInd)); yield return(Toils_Reserve.Reserve(HaulableInd)); yield return(Toils_Reserve.ReserveQueue(HaulableInd)); yield return(Toils_Jump.JumpIf(toilGoToThing, () => { return (CurJob.targetB.HasThing) ? true : false; })); //Collect TargetQueue { //Extract an haulable into TargetA yield return(extractB); yield return(toilGoToThing); //CollectIntoCarrier Toil toilPutInInventory = new Toil(); toilPutInInventory.initAction = () => { if (pawn.inventory.container.Count < backpack.MaxItem && backpack.wearer.inventory.container.TotalStackCount < backpack.MaxStack) { if (CurJob.targetB.Thing.TryGetComp <CompForbiddable>() != null && CurJob.targetB.Thing.TryGetComp <CompForbiddable>().Forbidden == true) { CurJob.targetB.Thing.TryGetComp <CompForbiddable>().Forbidden = false; } if (pawn.inventory.container.TryAdd(CurJob.targetB.Thing, CurJob.maxNumToCarry)) { CurJob.targetB.Thing.holder = pawn.inventory.GetContainer(); CurJob.targetB.Thing.holder.owner = pawn.inventory; backpack.numOfSavedItems++; } } else { this.EndJobWith(JobCondition.Incompletable); } }; yield return(toilPutInInventory); yield return(Toils_Jump.JumpIfHaveTargetInQueue(HaulableInd, extractB)); } }
public static Job HaulWithTools(Pawn pawn, Vehicle_Cart cart = null) { Trace.stopWatchStart(); //Job Setting JobDef jobDef; TargetInfo targetC; int maxItem; int thresholdItem; int reservedMaxItem; IEnumerable <Thing> remainingItems; bool ShouldDrop; Thing lastItem = ToolsForHaulUtility.TryGetBackpackLastItem(pawn); if (cart == null) { Apparel_Backpack backpack = ToolsForHaulUtility.TryGetBackpack(pawn); jobDef = jobDefHaulWithBackpack; targetC = backpack; maxItem = backpack.MaxItem; thresholdItem = (int)Math.Ceiling(maxItem * 0.5); reservedMaxItem = pawn.inventory.container.Count; remainingItems = pawn.inventory.container; ShouldDrop = true; if (lastItem != null) { for (int i = 0; i < pawn.inventory.container.Count; i++) { if (pawn.inventory.container[i] == lastItem && (reservedMaxItem - (i + 1)) <= 0) { ShouldDrop = false; break; } } } } else { jobDef = (cart.TryGetComp <CompMountable>().IsMounted&& cart.TryGetComp <CompMountable>().Driver.RaceProps.Animal)? jobDefHaulWithAnimalCart : jobDefHaulWithCart; targetC = cart; maxItem = cart.MaxItem; thresholdItem = (int)Math.Ceiling(maxItem * 0.5); reservedMaxItem = cart.storage.Count; remainingItems = cart.storage; ShouldDrop = (reservedMaxItem > 0) ? true : false; } Job job = new Job(jobDef); job.targetQueueA = new List <TargetInfo>(); job.targetQueueB = new List <TargetInfo>(); job.targetC = targetC; Trace.AppendLine(pawn.LabelCap + " In HaulWithTools: " + jobDef.defName + "\n" + "MaxItem: " + maxItem + " reservedMaxItem: " + reservedMaxItem); //Drop remaining item if (ShouldDrop) { Trace.AppendLine("Start Drop remaining item"); bool startDrop = false; for (int i = 0; i < remainingItems.Count(); i++) { if (cart == null && startDrop == false) { if (remainingItems.ElementAt(i) == lastItem) { startDrop = true; } else { continue; } } IntVec3 storageCell = FindStorageCell(pawn, remainingItems.ElementAt(i), job.targetQueueB); if (storageCell == IntVec3.Invalid) { break; } job.targetQueueB.Add(storageCell); } if (!job.targetQueueB.NullOrEmpty()) { Trace.AppendLine("Droping Job is issued"); Trace.LogMessage(); return(job); } if (cart != null && job.def == jobDefHaulWithCart && !cart.IsInValidStorage()) { Trace.AppendLine("In DismountInBase"); return(DismountInBase(pawn, cart)); } JobFailReason.Is(ToolsForHaulUtility.NoEmptyPlaceLowerTrans); Trace.AppendLine("End Drop remaining item"); Trace.AppendLine("No Job. Reason: " + JobFailReason.Reason); Trace.LogMessage(); return((Job)null); } //Collect item Trace.AppendLine("Start Collect item"); IntVec3 searchPos = (cart != null) ? cart.Position : pawn.Position; bool flag1 = false; foreach (SlotGroup slotGroup in Find.SlotGroupManager.AllGroupsListInPriorityOrder) { Trace.AppendLine("Start searching slotGroup"); if (slotGroup.CellsList.Count() - slotGroup.HeldThings.Count() < maxItem) { continue; } //Counting valid items Trace.AppendLine("Start Counting valid items"); int thingsCount = ListerHaulables.ThingsPotentiallyNeedingHauling().Count(item => slotGroup.Settings.AllowedToAccept(item)); //Finding valid items Trace.AppendLine("Start Finding valid items"); if (thingsCount > thresholdItem) { //ClosestThing_Global_Reachable Configuration Predicate <Thing> predicate = item => !job.targetQueueA.Contains(item) && !FireUtility.IsBurning(item) && ((cart != null && cart.allowances.Allows(item)) || cart == null) && slotGroup.Settings.AllowedToAccept(item) && pawn.CanReserveAndReach(item, PathEndMode.Touch, DangerUtility.NormalMaxDanger(pawn)); //&& !(item is UnfinishedThing && ((UnfinishedThing)item).BoundBill != null) //&& (item.def.IsNutritionSource && !SocialProperness.IsSociallyProper(item, pawn, false, false)); Thing thing = GenClosest.ClosestThing_Global_Reachable(searchPos, ListerHaulables.ThingsPotentiallyNeedingHauling(), PathEndMode.ClosestTouch, TraverseParms.For(TraverseMode.ByPawn, DangerUtility.NormalMaxDanger(pawn)), 9999, predicate); if (thing == null) { continue; } IntVec3 center = thing.Position; //Enqueue items in valid distance Trace.AppendLine("Start Enqueuing items in valid distance"); foreach (Thing item in ListerHaulables.ThingsPotentiallyNeedingHauling().Where(item => !job.targetQueueA.Contains(item) && !FireUtility.IsBurning(item) && ((cart != null && cart.allowances.Allows(item)) || cart == null) && slotGroup.Settings.AllowedToAccept(item) && pawn.CanReserveAndReach(item, PathEndMode.Touch, DangerUtility.NormalMaxDanger(pawn)) && center.DistanceToSquared(item.Position) <= ValidDistance)) { job.targetQueueA.Add(item); if (reservedMaxItem + job.targetQueueA.Count >= maxItem) { break; } } //Find storage cell Trace.AppendLine("Start Finding storage cell"); if (reservedMaxItem + job.targetQueueA.Count > thresholdItem) { List <IntVec3> availableCells = new List <IntVec3>(); foreach (IntVec3 cell in slotGroup.CellsList.Where(cell => ReservationUtility.CanReserve(pawn, cell) && cell.Standable() && cell.GetStorable() == null)) { job.targetQueueB.Add(cell); if (job.targetQueueB.Count >= job.targetQueueA.Count) { break; } } flag1 = true; break; } else { job.targetQueueA.Clear(); } } if (flag1) { break; } } Trace.AppendLine("Elapsed Time"); Trace.stopWatchStop(); //Check job is valid if (!job.targetQueueA.NullOrEmpty() && reservedMaxItem + job.targetQueueA.Count > thresholdItem && !job.targetQueueB.NullOrEmpty()) { Trace.AppendLine("Hauling Job is issued"); Trace.LogMessage(); return(job); } if (cart != null && job.def == jobDefHaulWithCart && !cart.IsInValidStorage()) { Trace.AppendLine("In DismountInBase: "); return(DismountInBase(pawn, cart)); } if (job.targetQueueA.NullOrEmpty()) { JobFailReason.Is(ToolsForHaulUtility.NoHaulable); } else if (reservedMaxItem + job.targetQueueA.Count <= thresholdItem) { JobFailReason.Is(ToolsForHaulUtility.TooLittleHaulable); } else if (job.targetQueueB.NullOrEmpty()) { JobFailReason.Is(ToolsForHaulUtility.NoEmptyPlaceLowerTrans); } Trace.AppendLine("No Job. Reason: " + JobFailReason.Reason); Trace.LogMessage(); return((Job)null); }
protected override IEnumerable <Toil> MakeNewToils() { Apparel_Backpack backpack = CurJob.GetTarget(BackpackInd).Thing as Apparel_Backpack; Thing lastItem = ToolsForHaulUtility.TryGetBackpackLastItem(pawn); /// //Set fail conditions /// /// //Define Toil /// Toil endOfJob = new Toil(); endOfJob.initAction = () => { EndJobWith(JobCondition.Succeeded); }; Toil checkStoreCellEmpty = Toils_Jump.JumpIf(endOfJob, () => CurJob.GetTargetQueue(StoreCellInd).NullOrEmpty()); Toil checkHaulableEmpty = Toils_Jump.JumpIf(checkStoreCellEmpty, () => CurJob.GetTargetQueue(HaulableInd).NullOrEmpty()); /// //Toils Start /// //Reserve thing to be stored and storage cell yield return(Toils_Reserve.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) .FailOnDestroyed(HaulableInd); yield return(gotoThing); yield return(ToolsForHaul.Toils_Collect.CollectInInventory(HaulableInd)); yield return(Toils_Collect.CheckDuplicates(gotoThing, BackpackInd, HaulableInd)); yield return(Toils_Jump.JumpIfHaveTargetInQueue(HaulableInd, extractA)); } //JumpIf toilEnd yield return(checkStoreCellEmpty); //Drop TargetQueue { Toil extractB = Toils_Collect.Extract(StoreCellInd); yield return(extractB); yield return(Toils_Goto.GotoCell(StoreCellInd, PathEndMode.ClosestTouch) .FailOnBurningImmobile(StoreCellInd)); yield return(ToolsForHaul.Toils_Collect.DropTheCarriedInCell(StoreCellInd, ThingPlaceMode.Direct, lastItem)); yield return(Toils_Jump.JumpIfHaveTargetInQueue(StoreCellInd, extractB)); } yield return(endOfJob); }