public override Job JobOnThing(Pawn pawn, Thing t) { Vehicle_Cart cart = t as Vehicle_Cart; if (cart == null) { return((Job)null); } if (cart.IsForbidden(pawn.Faction) || !ReservationUtility.CanReserveAndReach(pawn, cart, PathEndMode.ClosestTouch, DangerUtility.NormalMaxDanger(pawn))) { return((Job)null); } if (FireUtility.IsBurning(cart)) { JobFailReason.Is(ToolsForHaulUtility.BurningLowerTrans); return((Job)null); } if (ListerHaulables.ThingsPotentiallyNeedingHauling().Count == 0 && cart.storage.Count == 0) { JobFailReason.Is(ToolsForHaulUtility.NoHaulable); return((Job)null); } if (Find.SlotGroupManager.AllGroupsListInPriorityOrder.Count == 0) { JobFailReason.Is(ToolsForHaulUtility.NoEmptyPlaceLowerTrans); return((Job)null); } if (ToolsForHaulUtility.AvailableAnimalCart(cart) || ToolsForHaulUtility.AvailableCart(cart, pawn)) { return(ToolsForHaulUtility.HaulWithTools(pawn, cart)); } JobFailReason.Is(ToolsForHaulUtility.NoAvailableCart); return((Job)null); }
public static Toil CheckDuplicates(Toil jumpToil, TargetIndex CarrierInd, TargetIndex HaulableInd) { Toil toil = new Toil(); toil.initAction = () => { IntVec3 storeCell = IntVec3.Invalid; Pawn actor = toil.GetActor(); TargetInfo target = toil.actor.jobs.curJob.GetTarget(HaulableInd); if (target.Thing.def.stackLimit <= 1) { return; } List <TargetInfo> targetQueue = toil.actor.jobs.curJob.GetTargetQueue(HaulableInd); if (!targetQueue.NullOrEmpty() && target.Thing.def.defName == targetQueue.First().Thing.def.defName) { toil.actor.jobs.curJob.SetTarget(HaulableInd, targetQueue.First()); Find.Reservations.Reserve(actor, targetQueue.First()); targetQueue.RemoveAt(0); toil.actor.jobs.curDriver.JumpToToil(jumpToil); return; } Vehicle_Cart cart = toil.actor.jobs.curJob.GetTarget(CarrierInd).Thing as Vehicle_Cart; Apparel_Backpack backpack = toil.actor.jobs.curJob.GetTarget(CarrierInd).Thing as Apparel_Backpack; if (cart == null && backpack == null) { Log.Error(actor.LabelCap + " Report: Don't have Carrier"); toil.actor.jobs.curDriver.EndJobWith(JobCondition.Errored); return; } int curItemCount = (cart != null ? cart.storage.Count : backpack.slotsComp.slots.Count) + targetQueue.Count; int curItemStack = (cart != null ? cart.storage.TotalStackCount : backpack.slotsComp.slots.TotalStackCount) + targetQueue.Sum(item => item.Thing.stackCount); int maxItem = cart != null ? cart.MaxItem : backpack.MaxItem; int maxStack = cart != null ? cart.MaxStack : backpack.MaxStack; if (curItemCount >= maxItem || curItemStack >= maxStack) { return; } //Check target's nearby Thing thing = GenClosest.ClosestThing_Global_Reachable(actor.Position, ListerHaulables.ThingsPotentiallyNeedingHauling(), PathEndMode.Touch, TraverseParms.For(actor, Danger.Some), NearbyCell, item => !targetQueue.Contains(item) && item.def.defName == target.Thing.def.defName && !item.IsBurning() && Find.Reservations.CanReserve(actor, item)); if (thing != null) { toil.actor.jobs.curJob.SetTarget(HaulableInd, thing); Find.Reservations.Reserve(actor, thing); toil.actor.jobs.curDriver.JumpToToil(jumpToil); } }; return(toil); }
public override bool ShouldSkip(Pawn pawn) { // Ticker for checking special hauling cases of filling stacks in containers from stockpiles CFS_ListerHaulables.ListerHaulablesTick(); FindHaulablesInsideContainers(); // Skip if no haulables in any list (ListerHaulables.ThingsPotentiallyNeedingHauling() will still count things inside container as hauling required, but they won't be hauled because of future checks) return(ListerHaulables.ThingsPotentiallyNeedingHauling().Count == 0 && haulables_blockedInListerHaulables.Count == 0 && haulables_insideContainers.Count == 0 && CFS_ListerHaulables.haulables.Count == 0); }
public override IEnumerable <Thing> PotentialWorkThingsGlobal(Pawn pawn) { /* Required, because ListerHaulables removes things from haulables list, which are not fit in SlotGroups (can't stack things). * So i preserve the original list before it's changed after the first item is hauled to the destination point. */ if (ListerHaulables.ThingsPotentiallyNeedingHauling().Count >= haulables_blockedInListerHaulables.Count) { haulables_blockedInListerHaulables = new List <Thing>(ListerHaulables.ThingsPotentiallyNeedingHauling()); } // Merge all the required lists of haulables (original, blocked, inside containers and which are not counted at all, if containers already partially full (CFS_ListerHaulables.haulables), to fill the incomplete stacks) return(ListerHaulables.ThingsPotentiallyNeedingHauling().Union(haulables_blockedInListerHaulables).Union(haulables_insideContainers).Union(CFS_ListerHaulables.haulables).ToList()); }
public override IEnumerable <Thing> PotentialWorkThingsGlobal(Pawn pawn) { List <Thing> list = new List <Thing>(); Apparel_Backpack backpack = ToolsForHaulUtility.TryGetBackpack(pawn); foreach (Thing thing in ListerHaulables.ThingsPotentiallyNeedingHauling()) { if (thing.def.thingCategories.Exists(category => backpack.slotsComp.Properties.allowedThingCategoryDefs.Exists(subCategory => subCategory.ThisAndChildCategoryDefs.Contains(category)) && !backpack.slotsComp.Properties.forbiddenSubThingCategoryDefs.Exists(subCategory => subCategory.ThisAndChildCategoryDefs.Contains(category)))) { list.Add(thing); } //return ToolsForHaulUtility.Cart(); } return(list); }
public override bool ShouldSkip(Pawn pawn) { Trace.DebugWriteHaulingPawn(pawn); //Don't have haulables. if (ListerHaulables.ThingsPotentiallyNeedingHauling().Count == 0) { return(true); } //Should skip pawn that don't have backpack. if (ToolsForHaulUtility.TryGetBackpack(pawn) == null) { return(true); } return(false); }
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 Job TryGiveTerminalJob(Pawn pawn) { Thing closestHaulable; Job jobCollectThing = new Job(DefDatabase <JobDef> .GetNamed("CollectThing")); Job jobDropInCell = new Job(DefDatabase <JobDef> .GetNamed("DropInCell")); Job jobDismountInBase = new Job(DefDatabase <JobDef> .GetNamed("DismountInBase")); jobCollectThing.maxNumToCarry = 99999; jobCollectThing.haulMode = HaulMode.ToCellStorage; //Find Available Carrier Vehicle_Cargo carrier = Find.ListerThings.AllThings.Find((Thing t) => (t.TryGetComp <CompMountable>() != null && t.TryGetComp <CompMountable>().Driver == pawn)) as Vehicle_Cargo; //No Carrier if (carrier == null) { //Log.Message("No Carrier"); return(null); } jobCollectThing.targetC = carrier; jobDropInCell.targetC = carrier; jobDismountInBase.targetA = carrier; //collectThing Predicate Predicate <Thing> predicate = (Thing t) => (!t.IsForbidden(pawn.Faction) && !t.IsInAnyStorage() && pawn.CanReserve(t) && carrier.storage.CanAcceptAnyOf(t)); //Log.Message("flagInProgressDrop" + flagInProgressDrop); if (carrier.storage.TotalStackCount < carrier.GetMaxStackCount && carrier.storage.Contents.Count() < carrier.maxItem && !ListerHaulables.ThingsPotentiallyNeedingHauling().NullOrEmpty() && flagInProgressDrop == false) { //Log.Message("Finding Haulable"); closestHaulable = GenClosest.ClosestThing_Global_Reachable(pawn.Position, ListerHaulables.ThingsPotentiallyNeedingHauling(), PathMode.ClosestTouch, TraverseParms.For(pawn, Danger.Deadly, false), 9999, predicate); if (closestHaulable == null) { //Log.Message("No Haulable"); return(null); } jobCollectThing.targetA = closestHaulable; return(jobCollectThing); } else { //Log.Message("flagInProgressDrop" + flagInProgressDrop); flagInProgressDrop = true; if (carrier.storage.Contents.Count() <= 0) { flagInProgressDrop = false; //Log.Message("End Progress Drop"); if (ListerHaulables.ThingsPotentiallyNeedingHauling().NullOrEmpty()) { return(jobDismountInBase); } return(null); } foreach (Zone zone in Find.ZoneManager.AllZones) { if (zone is Zone_Stockpile) { foreach (var zoneCell in zone.cells) { Thing dropThing = carrier.storage.Contents.Last(); if (zoneCell.IsValidStorageFor(dropThing) && pawn.CanReserve(zoneCell)) { jobDropInCell.targetA = dropThing; jobDropInCell.targetB = zoneCell; return(jobDropInCell); } } } } //No zone for stock //Log.Message("No Zone"); return(null); } }
protected override Job TryGiveJob(Pawn pawn) { Predicate <Thing> validator = (Thing t) => !t.IsForbidden(pawn) && HaulAIUtility.PawnCanAutomaticallyHaulFast(pawn, t); //Start my code Thing thing = null; List <Thing> things = ListerHaulables.ThingsPotentiallyNeedingHauling(); List <Thing> degrade = new List <Thing>(); List <Thing> undegrade = new List <Thing>(); foreach (Thing t in things) { if (t.GetStatValue(StatDefOf.DeteriorationRate) > 0) { degrade.Add(t); } else { undegrade.Add(t); } } //Loop through all haul areas in order foreach (Area a in AreaFinder.getHaulAreas()) { //Check if got degradable item thing = GenClosest.ClosestThing_Global_Reachable(pawn.Position, AreaFinder.searcher(a, degrade), PathEndMode.OnCell, TraverseParms.For(pawn, Danger.Deadly, TraverseMode.ByPawn, false), 9999f, validator, null); if (thing != null) { break; } //Check if got undegradable item thing = GenClosest.ClosestThing_Global_Reachable(pawn.Position, AreaFinder.searcher(a, undegrade), PathEndMode.OnCell, TraverseParms.For(pawn, Danger.Deadly, TraverseMode.ByPawn, false), 9999f, validator, null); if (thing != null) { break; } } if (thing == null) { thing = GenClosest.ClosestThing_Global_Reachable(pawn.Position, degrade, PathEndMode.OnCell, TraverseParms.For(pawn, Danger.Deadly, TraverseMode.ByPawn, false), 9999f, validator, null); if (thing == null) { thing = GenClosest.ClosestThing_Global_Reachable(pawn.Position, undegrade, PathEndMode.OnCell, TraverseParms.For(pawn, Danger.Deadly, TraverseMode.ByPawn, false), 9999f, validator, null); } } /* old 50 cell code * Thing thing = GenClosest.ClosestThing_Global_Reachable(pawn.Position, degrade, PathEndMode.OnCell, TraverseParms.For(pawn, Danger.Deadly, TraverseMode.ByPawn, false), 50f, validator, null); * if (thing == null) * { * thing = GenClosest.ClosestThing_Global_Reachable(pawn.Position, undegrade, PathEndMode.OnCell, TraverseParms.For(pawn, Danger.Deadly, TraverseMode.ByPawn, false), 50f, validator, null); * if (thing == null) * { * thing = GenClosest.ClosestThing_Global_Reachable(pawn.Position, degrade, PathEndMode.OnCell, TraverseParms.For(pawn, Danger.Deadly, TraverseMode.ByPawn, false), 9999f, validator, null); * if (thing == null) * { * thing = GenClosest.ClosestThing_Global_Reachable(pawn.Position, undegrade, PathEndMode.OnCell, TraverseParms.For(pawn, Danger.Deadly, TraverseMode.ByPawn, false), 9999f, validator, null); * } * } * }*/ //End my code if (thing != null) { return(HaulAIUtility.HaulToStorageJob(pawn, thing)); } return(null); }
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); }
public override Job JobOnThing(Pawn pawn, Thing t) { if (!(t is Vehicle_Cargo)) { return(null); } Vehicle_Cargo carrier = t as Vehicle_Cargo; List <Thing> haulables = ListerHaulables.ThingsPotentiallyNeedingHauling(); IEnumerable <Thing> remainingItems = carrier.storage.Contents; //bool IsMountedVehicle = ((carrier.GetComp<CompMountable>().Driver == pawn)? true: false); int reservedStackCount = carrier.storage.TotalStackCount; int reservedMaxItem = carrier.storage.Contents.Count(); Job jobDismountInBase = new Job(DefDatabase <JobDef> .GetNamed("DismountInBase")); Job jobCollect = new Job(DefDatabase <JobDef> .GetNamed("Collect")); jobCollect.maxNumToCarry = 99999; jobCollect.haulMode = HaulMode.ToCellStorage; jobCollect.targetQueueA = new List <TargetInfo>(); jobCollect.targetQueueB = new List <TargetInfo>(); //Set carrier jobDismountInBase.targetA = carrier; jobCollect.targetC = carrier; ReservationUtility.Reserve(pawn, t); //If IgnoreForbidden is true, add forbidden if (carrier.ignoreForbidden) { List <Thing> forbiddens = Find.ListerThings.AllThings.FindAll((Thing thing) => (thing.TryGetComp <CompForbiddable>() != null && thing.TryGetComp <CompForbiddable>().Forbidden == true)); haulables = forbiddens.Concat(haulables).ToList(); /*string logStr = ""; * foreach (var forbidden in forbiddens) * logStr += forbidden.ThingID; * Log.Message("Haulable: " + logStr);*/ } //Drop remaining item foreach (var remainingItem in remainingItems) { IntVec3 storageCell = new IntVec3(-1000, -1000, -1000); foreach (Zone zone in Find.ZoneManager.AllZones) { if (storageCell.IsValid) { break; } if (zone is Zone_Stockpile) { foreach (var zoneCell in zone.cells) { if (!jobCollect.targetQueueB.Contains(zoneCell) && zoneCell.IsValidStorageFor(remainingItem) && pawn.CanReserve(zoneCell)) { storageCell = zoneCell; break; } } } } if (!storageCell.IsValid) { break; } //Just drop, not collect. It was already collected //jobCollect.targetQueueA.Add(remainingItem); //ReservationUtility.Reserve(pawn, remainingItem, ReservationType.Total); jobCollect.targetQueueB.Add(storageCell); ReservationUtility.Reserve(pawn, storageCell); } if (!jobCollect.targetQueueB.NullOrEmpty()) { return(jobCollect); } //collectThing Predicate Predicate <Thing> predicate = (Thing item) => ((carrier.ignoreForbidden || !item.IsForbidden(pawn.Faction)) && !item.IsInValidStorage() && pawn.CanReserve(item) && carrier.storage.CanAcceptAnyOf(item)); //Collect and drop item while (!haulables.NullOrEmpty() && reservedStackCount < carrier.GetMaxStackCount && reservedMaxItem < carrier.maxItem) { IntVec3 storageCell = new IntVec3(-1000, -1000, -1000); Thing closestHaulable = null; //Log.Message("reservedStackCount, reservedMaxItem :" + reservedStackCount + ',' + reservedMaxItem); closestHaulable = GenClosest.ClosestThing_Global_Reachable(pawn.Position, haulables, PathMode.ClosestTouch, TraverseParms.For(pawn, Danger.Deadly, false), 9999, predicate); if (closestHaulable == null) { break; } if (!jobCollect.targetQueueB.NullOrEmpty()) { foreach (TargetInfo target in jobCollect.targetQueueB) { if (storageCell.IsValid) { break; } foreach (var adjCell in GenAdjFast.AdjacentCells8Way(target)) { if (!jobCollect.targetQueueB.Contains(adjCell) && adjCell.IsValidStorageFor(closestHaulable) && pawn.CanReserve(adjCell)) { storageCell = adjCell; break; } } } } foreach (Zone zone in Find.ZoneManager.AllZones) { if (storageCell.IsValid) { break; } if (zone is Zone_Stockpile) { foreach (var zoneCell in zone.cells) { if (!jobCollect.targetQueueB.Contains(zoneCell) && zoneCell.IsValidStorageFor(closestHaulable) && pawn.CanReserve(zoneCell)) { storageCell = zoneCell; //Log.Message("storageCell: " + storageCell); break; } } } } //No Storage if (!storageCell.IsValid) { break; } jobCollect.targetQueueA.Add(closestHaulable); ReservationUtility.Reserve(pawn, closestHaulable); haulables.Remove(closestHaulable); jobCollect.targetQueueB.Add(storageCell); ReservationUtility.Reserve(pawn, storageCell); reservedMaxItem++; reservedStackCount += closestHaulable.stackCount; } //No haulables or zone if (jobCollect.targetQueueA.NullOrEmpty() || jobCollect.targetQueueB.NullOrEmpty()) { foreach (Zone zone in Find.ZoneManager.AllZones) { if (jobDismountInBase.targetB != null) { break; } if (zone is Zone_Stockpile) { foreach (var zoneCell in zone.cells) { Thing dropThing = carrier; if (zoneCell.IsValidStorageFor(dropThing) && pawn.CanReserve(zoneCell)) { ReservationUtility.Reserve(pawn, zoneCell); jobDismountInBase.targetB = zoneCell; break; } } } } //Move cargo in Base if (!carrier.IsInValidStorage() && jobDismountInBase.targetB != null) { return(jobDismountInBase); } //No job, no move to cargo if (Find.Reservations.IsReserved(carrier, pawn.Faction)) { Find.Reservations.Release(carrier, pawn); } return(null); } return(jobCollect); }
public override Job JobOnThing(Pawn pawn, Thing t) { Vehicle_Cart cart = null; if (!HaulAIUtility.PawnCanAutomaticallyHaulFast(pawn, t)) { return(null); } // Vehicle selection if (ToolsForHaulUtility.IsDriver(pawn)) { cart = ToolsForHaulUtility.GetCartByDriver(pawn); if (cart == null) { // JobFailReason.Is("Can't haul with military vehicle"); return(ToolsForHaulUtility.DismountInBase(pawn, MapComponent_ToolsForHaul.currentVehicle[pawn])); } } if (cart == null) { cart = RightTools.GetRightVehicle(pawn, WorkTypeDefOf.Hauling, t) as Vehicle_Cart; if (cart == null) { return(null); } } if (cart.IsBurning()) { JobFailReason.Is(ToolsForHaulUtility.BurningLowerTrans); return(null); } if (!cart.allowances.Allows(t)) { JobFailReason.Is("Cart does not allow that thing"); return(null); } if (ListerHaulables.ThingsPotentiallyNeedingHauling().Count == 0 && cart.storage.Count == 0) { JobFailReason.Is("NoHaulable".Translate()); return(null); } if (Find.SlotGroupManager.AllGroupsListInPriorityOrder.Count == 0) { JobFailReason.Is(ToolsForHaulUtility.NoEmptyPlaceLowerTrans); return(null); } if (ToolsForHaulUtility.AvailableAnimalCart(cart) || ToolsForHaulUtility.AvailableVehicle(pawn, cart)) { return(ToolsForHaulUtility.HaulWithTools(pawn, cart, t)); } JobFailReason.Is(ToolsForHaulUtility.NoAvailableCart); return(null); }
public override IEnumerable <Thing> PotentialWorkThingsGlobal(Pawn pawn) { //return ToolsForHaulUtility.Cart(); return(ListerHaulables.ThingsPotentiallyNeedingHauling()); }