private static bool TryFindBestBillIngredients(Bill bill, Pawn pawn, Thing billGiver, List <ThingCount> chosen) { chosen.Clear(); newRelevantThings.Clear(); if (bill.recipe.ingredients.Count == 0) { return(true); } IntVec3 rootCell = GetBillGiverRootCell(billGiver, pawn); Region rootReg = rootCell.GetRegion(pawn.Map); if (rootReg == null) { return(false); } MakeIngredientsListInProcessingOrder(ingredientsOrdered, bill); relevantThings.Clear(); processedThings.Clear(); bool foundAll = false; Predicate <Thing> baseValidator = (Thing t) => t.Spawned && !t.IsForbidden(pawn) && (float)(t.Position - billGiver.Position).LengthHorizontalSquared < bill.ingredientSearchRadius * bill.ingredientSearchRadius && bill.IsFixedOrAllowedIngredient(t) && bill.recipe.ingredients.Any((IngredientCount ingNeed) => ingNeed.filter.Allows(t)) && pawn.CanReserve(t); bool billGiverIsPawn = billGiver is Pawn; if (billGiverIsPawn) { AddEveryMedicineToRelevantThings(pawn, billGiver, relevantThings, baseValidator, pawn.Map); if (TryFindBestBillIngredientsInSet(relevantThings, bill, chosen, rootCell, billGiverIsPawn)) { relevantThings.Clear(); ingredientsOrdered.Clear(); return(true); } } TraverseParms traverseParams = TraverseParms.For(pawn); RegionEntryPredicate entryCondition = null; if (Math.Abs(999f - bill.ingredientSearchRadius) >= 1f) { float radiusSq = bill.ingredientSearchRadius * bill.ingredientSearchRadius; entryCondition = delegate(Region from, Region r) { if (!r.Allows(traverseParams, isDestination: false)) { return(false); } CellRect extentsClose = r.extentsClose; int num2 = Math.Abs(billGiver.Position.x - Math.Max(extentsClose.minX, Math.Min(billGiver.Position.x, extentsClose.maxX))); if ((float)num2 > bill.ingredientSearchRadius) { return(false); } int num3 = Math.Abs(billGiver.Position.z - Math.Max(extentsClose.minZ, Math.Min(billGiver.Position.z, extentsClose.maxZ))); return(!((float)num3 > bill.ingredientSearchRadius) && (float)(num2 * num2 + num3 * num3) <= radiusSq); }; } else { entryCondition = ((Region from, Region r) => r.Allows(traverseParams, isDestination: false)); } int adjacentRegionsAvailable = rootReg.Neighbors.Count((Region region) => entryCondition(rootReg, region)); int regionsProcessed = 0; processedThings.AddRange(relevantThings); RegionProcessor regionProcessor = delegate(Region r) { List <Thing> list = r.ListerThings.ThingsMatching(ThingRequest.ForGroup(ThingRequestGroup.HaulableEver)); for (int i = 0; i < list.Count; i++) { Thing thing = list[i]; if (!processedThings.Contains(thing) && ReachabilityWithinRegion.ThingFromRegionListerReachable(thing, r, PathEndMode.ClosestTouch, pawn) && baseValidator(thing) && !(thing.def.IsMedicine & billGiverIsPawn)) { newRelevantThings.Add(thing); processedThings.Add(thing); } } int num = ++regionsProcessed; if (newRelevantThings.Count > 0 && regionsProcessed > adjacentRegionsAvailable) { relevantThings.AddRange(newRelevantThings); newRelevantThings.Clear(); if (TryFindBestBillIngredientsInSet(relevantThings, bill, chosen, rootCell, billGiverIsPawn)) { foundAll = true; return(true); } } return(false); }; RegionTraverser.BreadthFirstTraverse(rootReg, entryCondition, regionProcessor, 99999); relevantThings.Clear(); newRelevantThings.Clear(); processedThings.Clear(); ingredientsOrdered.Clear(); return(foundAll); }
private static bool TryFindBestBillIngredients(Bill bill, Pawn pawn, Thing billGiver, List <ThingCount> chosen) { chosen.Clear(); WorkGiver_DoBill.newRelevantThings.Clear(); if (bill.recipe.ingredients.Count == 0) { return(true); } IntVec3 rootCell = WorkGiver_DoBill.GetBillGiverRootCell(billGiver, pawn); Region rootReg = rootCell.GetRegion(pawn.Map, RegionType.Set_Passable); if (rootReg == null) { return(false); } WorkGiver_DoBill.MakeIngredientsListInProcessingOrder(WorkGiver_DoBill.ingredientsOrdered, bill); WorkGiver_DoBill.relevantThings.Clear(); WorkGiver_DoBill.processedThings.Clear(); bool foundAll = false; Predicate <Thing> baseValidator = (Thing t) => t.Spawned && !t.IsForbidden(pawn) && (float)(t.Position - billGiver.Position).LengthHorizontalSquared < bill.ingredientSearchRadius * bill.ingredientSearchRadius && bill.IsFixedOrAllowedIngredient(t) && bill.recipe.ingredients.Any((IngredientCount ingNeed) => ingNeed.filter.Allows(t)) && pawn.CanReserve(t, 1, -1, null, false); bool billGiverIsPawn = billGiver is Pawn; if (billGiverIsPawn) { WorkGiver_DoBill.AddEveryMedicineToRelevantThings(pawn, billGiver, WorkGiver_DoBill.relevantThings, baseValidator, pawn.Map); if (WorkGiver_DoBill.TryFindBestBillIngredientsInSet(WorkGiver_DoBill.relevantThings, bill, chosen)) { WorkGiver_DoBill.relevantThings.Clear(); WorkGiver_DoBill.ingredientsOrdered.Clear(); return(true); } } TraverseParms traverseParams = TraverseParms.For(pawn, Danger.Deadly, TraverseMode.ByPawn, false); RegionEntryPredicate entryCondition = (Region from, Region r) => r.Allows(traverseParams, false); int adjacentRegionsAvailable = rootReg.Neighbors.Count((Region region) => entryCondition(rootReg, region)); int regionsProcessed = 0; WorkGiver_DoBill.processedThings.AddRange(WorkGiver_DoBill.relevantThings); RegionProcessor regionProcessor = delegate(Region r) { List <Thing> list = r.ListerThings.ThingsMatching(ThingRequest.ForGroup(ThingRequestGroup.HaulableEver)); for (int i = 0; i < list.Count; i++) { Thing thing = list[i]; if (!WorkGiver_DoBill.processedThings.Contains(thing)) { if (ReachabilityWithinRegion.ThingFromRegionListerReachable(thing, r, PathEndMode.ClosestTouch, pawn)) { if (baseValidator(thing) && (!thing.def.IsMedicine || !billGiverIsPawn)) { WorkGiver_DoBill.newRelevantThings.Add(thing); WorkGiver_DoBill.processedThings.Add(thing); } } } } regionsProcessed++; if (WorkGiver_DoBill.newRelevantThings.Count > 0 && regionsProcessed > adjacentRegionsAvailable) { Comparison <Thing> comparison = delegate(Thing t1, Thing t2) { float num = (float)(t1.Position - rootCell).LengthHorizontalSquared; float value = (float)(t2.Position - rootCell).LengthHorizontalSquared; return(num.CompareTo(value)); }; WorkGiver_DoBill.newRelevantThings.Sort(comparison); WorkGiver_DoBill.relevantThings.AddRange(WorkGiver_DoBill.newRelevantThings); WorkGiver_DoBill.newRelevantThings.Clear(); if (WorkGiver_DoBill.TryFindBestBillIngredientsInSet(WorkGiver_DoBill.relevantThings, bill, chosen)) { foundAll = true; return(true); } } return(false); }; RegionTraverser.BreadthFirstTraverse(rootReg, entryCondition, regionProcessor, 99999, RegionType.Set_Passable); WorkGiver_DoBill.relevantThings.Clear(); WorkGiver_DoBill.newRelevantThings.Clear(); WorkGiver_DoBill.processedThings.Clear(); WorkGiver_DoBill.ingredientsOrdered.Clear(); return(foundAll); }