private void LogTrace(string level, string s) { if (!TraceEnabled) { return; } lock (Trace) { Trace.Append(DateTime.UtcNow.ToString("yyyy-MM-dd HH:mm:ss")); Trace.Append(" "); Trace.Append(level); Trace.Append(" "); Trace.AppendLine(s); } }
public static Job DismountInBase(Pawn pawn, Thing cart) { Job job = new Job(HaulJobDefOf.DismountInBase); job.targetA = cart; job.targetB = FindStorageCell(pawn, cart); if (job.targetB != IntVec3.Invalid) { Trace.AppendLine("DismountInBase Job is issued"); Trace.LogMessage(); return(job); } JobFailReason.Is(NoEmptyPlaceForCart); Trace.AppendLine("No Job. Reason: " + JobFailReason.Reason); Trace.LogMessage(); return(null); }
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); }
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); }