protected override IEnumerable <Toil> MakeNewToils()
        {
            this.FailOn(() => PrisonerFoodReservation.isReserved(TargetA.Thing));
            yield return(Toils_Reserve.Reserve(TargetIndex.B, 1, -1, null));

            if (eatingFromInventory)
            {
                yield return(Toils_Misc.TakeItemFromInventoryToCarrier(pawn, TargetIndex.A));
            }
            else if (usingNutrientPasteDispenser)
            {
                yield return(Toils_Goto.GotoThing(TargetIndex.A, PathEndMode.InteractionCell)
                             .FailOnForbidden(TargetIndex.A));

                yield return(Toils_Ingest.TakeMealFromDispenser(TargetIndex.A, pawn));
            }
            else
            {
                yield return(Toils_Reserve.Reserve(TargetIndex.A, 1, -1, null));

                yield return(Toils_Goto.GotoThing(TargetIndex.A, PathEndMode.ClosestTouch)
                             .FailOnForbidden(TargetIndex.A));

                yield return(Toils_Ingest.PickupIngestible(TargetIndex.A, Deliveree));
            }
            var toil = new Toil();

            toil.initAction = delegate
            {
                var actor  = toil.actor;
                var curJob = actor.jobs.curJob;
                actor.pather.StartPath(curJob.targetC, PathEndMode.OnCell);
            };
            toil.defaultCompleteMode = ToilCompleteMode.PatherArrival;
            toil.FailOnDestroyedNullOrForbidden(TargetIndex.B);
            toil.AddFailCondition(delegate
            {
                var pawn = (Pawn)toil.actor.jobs.curJob.targetB.Thing;
                return(!pawn.IsPrisonerOfColony || !pawn.guest.CanBeBroughtFood);
            });
            yield return(toil);

            yield return(new Toil
            {
                initAction = delegate
                {
                    Thing thing;
                    pawn.carryTracker.TryDropCarriedThing(toil.actor.jobs.curJob.targetC.Cell, ThingPlaceMode.Direct,
                                                          out thing, null);
                    PrisonerFoodReservation.reserve(thing, (Pawn)toil.actor.jobs.curJob.targetB.Thing);
                },
                defaultCompleteMode = ToilCompleteMode.Instant
            });
        }
Exemplo n.º 2
0
        public static Thing BestFoodSourceOnMap(Pawn getter, Pawn eater, bool desperate,
                                                FoodPreferability maxPref = FoodPreferability.MealLavish, bool allowPlant = true, bool allowDrug = true,
                                                bool allowCorpse          = true, bool allowDispenserFull     = true, bool allowDispenserEmpty = true,
                                                bool allowForbidden       = false, bool allowSociallyImproper = false)
        {
            var getterCanManipulate = getter.RaceProps.ToolUser &&
                                      getter.health.capacities.CapableOf(PawnCapacityDefOf.Manipulation);

            if (!getterCanManipulate && getter != eater)
            {
                Log.Error(string.Concat(getter, " tried to find food to bring to ", eater, " but ", getter,
                                        " is incapable of Manipulation."));
                return(null);
            }
            FoodPreferability minPref;

            if (!eater.RaceProps.Humanlike || eater == getter && eater.IsPrisoner)
            {
                minPref = FoodPreferability.NeverForNutrition;
            }
            else if (desperate)
            {
                minPref = FoodPreferability.DesperateOnly;
            }
            else
            {
                minPref = eater.needs.food.CurCategory <= HungerCategory.UrgentlyHungry
                    ? FoodPreferability.RawBad
                    : FoodPreferability.MealAwful;
            }
            Predicate <Thing> foodValidator = delegate(Thing t)
            {
                if (PrisonerFoodReservation.isReserved(t) && (eater != getter || !eater.IsPrisoner) && !desperate)
                {
                    return(false);
                }
                if (!allowForbidden && t.IsForbidden(getter))
                {
                    return(false);
                }
                var building_NutrientPasteDispenser = t as Building_NutrientPasteDispenser;
                if (building_NutrientPasteDispenser != null)
                {
                    if (!allowDispenserFull || ThingDefOf.MealNutrientPaste.ingestible.preferability < minPref ||
                        ThingDefOf.MealNutrientPaste.ingestible.preferability > maxPref || !getterCanManipulate ||
                        t.Faction != getter.Faction && t.Faction != getter.HostFaction ||
                        !building_NutrientPasteDispenser.powerComp.PowerOn ||
                        !allowDispenserEmpty && !building_NutrientPasteDispenser.HasEnoughFeedstockInHoppers() ||
                        !IsFoodSourceOnMapSociallyProper(t, getter, eater, allowSociallyImproper) ||
                        !t.InteractionCell.Standable(t.Map) || !getter.Map.reachability.CanReachNonLocal(
                            getter.Position, new TargetInfo(t.InteractionCell, t.Map, false), PathEndMode.OnCell,
                            TraverseParms.For(getter, Danger.Some, TraverseMode.ByPawn, false)))
                    {
                        return(false);
                    }
                }
                else
                {
                    if (t.def.ingestible.preferability < minPref)
                    {
                        return(false);
                    }
                    if (t.def.ingestible.preferability > maxPref)
                    {
                        return(false);
                    }
                    if (!t.IngestibleNow || !t.def.IsNutritionGivingIngestible || !allowCorpse && t is Corpse ||
                        !allowDrug && t.def.IsDrug || !desperate && t.IsNotFresh() || t.IsDessicated() ||
                        !eater.RaceProps.WillAutomaticallyEat(t) ||
                        !IsFoodSourceOnMapSociallyProper(t, getter, eater, allowSociallyImproper) ||
                        !getter.AnimalAwareOf(t) || !getter.CanReserve(t, 1, -1, null, false))
                    {
                        return(false);
                    }
                }
                return(true);
            };
            ThingRequest thingRequest;

            if ((eater.RaceProps.foodType & (FoodTypeFlags.Plant | FoodTypeFlags.Tree)) != FoodTypeFlags.None &&
                allowPlant)
            {
                thingRequest = ThingRequest.ForGroup(ThingRequestGroup.FoodSource);
            }
            else
            {
                thingRequest = ThingRequest.ForGroup(ThingRequestGroup.FoodSourceNotPlantOrTree);
            }
            Thing thing;

            if (getter.RaceProps.Humanlike)
            {
                var validator = foodValidator;
                thing = SpawnedFoodSearchInnerScan(eater, getter.Position,
                                                   getter.Map.listerThings.ThingsMatching(thingRequest), PathEndMode.ClosestTouch,
                                                   TraverseParms.For(getter, Danger.Deadly, TraverseMode.ByPawn, false), 9999f, validator);
            }
            else
            {
                var searchRegionsMax = 30;
                if (getter.Faction == Faction.OfPlayer)
                {
                    searchRegionsMax = 100;
                }
                filtered.Clear();
                foreach (var current in GenRadial.RadialDistinctThingsAround(getter.Position, getter.Map, 2f, true))
                {
                    var pawn = current as Pawn;
                    if (pawn != null && pawn != getter && pawn.RaceProps.Animal && pawn.CurJob != null &&
                        pawn.CurJob.def == JobDefOf.Ingest && pawn.CurJob.GetTarget(TargetIndex.A).HasThing)
                    {
                        filtered.Add(pawn.CurJob.GetTarget(TargetIndex.A).Thing);
                    }
                }
                var flag = !allowForbidden && ForbidUtility.CaresAboutForbidden(getter, true) &&
                           getter.playerSettings != null &&
                           getter.playerSettings.EffectiveAreaRestrictionInPawnCurrentMap != null;
                Predicate <Thing> predicate = t =>
                                              foodValidator(t) && !filtered.Contains(t) &&
                                              t.def.ingestible.preferability > FoodPreferability.DesperateOnly && !t.IsNotFresh();
                var validator = predicate;
                var ignoreEntirelyForbiddenRegions = flag;
                thing = GenClosest.ClosestThingReachable(getter.Position, getter.Map, thingRequest,
                                                         PathEndMode.ClosestTouch, TraverseParms.For(getter, Danger.Deadly, TraverseMode.ByPawn, false),
                                                         9999f, validator, null, 0, searchRegionsMax, false, RegionType.Set_Passable,
                                                         ignoreEntirelyForbiddenRegions);
                filtered.Clear();
                if (thing == null)
                {
                    desperate = true;
                    validator = foodValidator;
                    ignoreEntirelyForbiddenRegions = flag;
                    thing = GenClosest.ClosestThingReachable(getter.Position, getter.Map, thingRequest,
                                                             PathEndMode.ClosestTouch, TraverseParms.For(getter, Danger.Deadly, TraverseMode.ByPawn, false),
                                                             9999f, validator, null, 0, searchRegionsMax, false, RegionType.Set_Passable,
                                                             ignoreEntirelyForbiddenRegions);
                }
            }
            return(thing);
        }