internal static Thing _BestFoodSourceFor(Pawn getter, Pawn eater, bool fullDispensersOnly, out ThingDef foodDef)
        {
            var dispenserValidator = new DispenserValidator();

            dispenserValidator.getter             = getter;
            dispenserValidator.fullDispensersOnly = fullDispensersOnly;

            Thing bestFoodSpawnedFor = FoodUtility.BestFoodSpawnedFor(getter, eater, getter == eater);

            if (
                (getter == eater) &&
                (getter.RaceProps.predator) &&
                (bestFoodSpawnedFor == null)
                )
            {
                Pawn prey = BestPawnToHuntForPredator(getter);
                if (prey != null)
                {
                    foodDef = prey.RaceProps.corpseDef;
                    return((Thing)prey);
                }
            }

            if (getter.RaceProps.ToolUser)
            {
                // Try to find a working nutrient paste dispenser or food sythesizer
                var validatorPredicate = new Predicate <Thing>(dispenserValidator.Validate);
                var dispensers         = Find.ListerThings.AllThings.Where(t => (
                                                                               (t is Building_NutrientPasteDispenser) ||
                                                                               (
                                                                                   (t is Building_AutomatedFactory) &&
                                                                                   (((Building_AutomatedFactory)t).CompAutomatedFactory.Properties.outputVector == FactoryOutputVector.DirectToPawn)
                                                                               )
                                                                               ));
                if (dispensers.Any())
                {
                    // Check dispenses and synthesizers (automated factories)
                    if (bestFoodSpawnedFor != null)
                    {
                        // Compare with best spawned meal
                        float dist = (getter.Position - bestFoodSpawnedFor.Position).LengthManhattan;
                        dispenserValidator.meal.thing = bestFoodSpawnedFor;
                        dispenserValidator.meal.def   = bestFoodSpawnedFor.def;
                        dispenserValidator.meal.score = FoodOptimality(bestFoodSpawnedFor, dist);
                    }
                    else
                    {
                        // Nothing to compare to
                        dispenserValidator.meal.thing = null;
                        dispenserValidator.meal.def   = null;
                        dispenserValidator.meal.score = FoodOptimalityUnusable;
                    }

                    // Now find the best/closest dispenser
                    var dispenser = GenClosest.ClosestThingReachable(
                        getter.Position,
                        ThingRequest.ForUndefined(),
                        PathEndMode.InteractionCell,
                        TraverseParms.For(
                            dispenserValidator.getter,
                            dispenserValidator.getter.NormalMaxDanger()),
                        9999f,
                        validatorPredicate,
                        dispensers,
                        -1,
                        true);

                    if (dispenser != null)
                    {
                        // Found a dispenser/synthesizer and it's better than the spawned meal
                        foodDef = dispenserValidator.meal.def;
                        return(dispenser);
                    }
                }
            }
            foodDef = bestFoodSpawnedFor == null ? null : bestFoodSpawnedFor.def;
            return(bestFoodSpawnedFor);
        }
Exemple #2
0
        internal static Thing               _BestFoodSourceOnMap(Pawn getter, Pawn eater, bool desperate, FoodPreferability maxPref = FoodPreferability.MealLavish, bool allowPlant = true, bool allowLiquor = true, bool allowCorpse = true, bool allowDispenserFull = true, bool allowDispenserEmpty = true, bool allowForbidden = false)
        {
            Profiler.BeginSample("BestFoodInWorldFor getter=" + getter.LabelCap + " eater=" + eater.LabelCap);

            var getterCanManipulate = (
                (getter.RaceProps.ToolUser) &&
                (getter.health.capacities.CapableOf(PawnCapacityDefOf.Manipulation))
                );

            if (
                (!getterCanManipulate) &&
                (getter != eater)
                )
            {
                Log.Error(string.Format("{0} tried to find food to bring to {1} but {0} is incapable of Manipulation.", getter.LabelCap, eater.LabelCap));
                Profiler.EndSample();
                return(null);
            }

            var validator = new DispenserValidator();

            validator.getterCanManipulate = getterCanManipulate;
            validator.allowDispenserFull  = allowDispenserFull;
            validator.maxPref             = maxPref;
            validator.allowForbidden      = allowForbidden;
            validator.getter = getter;
            validator.allowDispenserEmpty = allowDispenserEmpty;
            validator.allowCorpse         = allowCorpse;
            validator.allowLiquor         = allowLiquor;
            validator.desperate           = desperate;
            validator.eater        = eater;
            validator.allowLiquor &= !desperate;
            validator.minPref      =
                desperate
                ? FoodPreferability.DesperateOnly
                :
                !eater.RaceProps.Humanlike
                    ? FoodPreferability.NeverForNutrition
                    :
                eater.needs.food.CurCategory >= HungerCategory.UrgentlyHungry
                        ? FoodPreferability.RawBad
                        : FoodPreferability.MealAwful;

            var thingRequest =
                (
                    ((eater.RaceProps.foodType & (FoodTypeFlags.Plant | FoodTypeFlags.Tree)) == FoodTypeFlags.None) ||
                    (!allowPlant)
                )
                ? ThingRequest.ForGroup(ThingRequestGroup.FoodSourceNotPlantOrTree)
                : ThingRequest.ForGroup(ThingRequestGroup.FoodSource);

            var thingsRequested = Find.ListerThings.ThingsMatching(thingRequest);
            //DumpThingsRequestedForGroup( thingRequest, thingsRequested );

            var potentialFoodSource = (Thing)null;

            if (getter.RaceProps.Humanlike)
            {
                //CCL_Log.Message( "Humanlike inner scan..." );
                potentialFoodSource = SpawnedFoodSearchInnerScan(
                    eater,
                    getter.Position,
                    thingsRequested,
                    PathEndMode.ClosestTouch,
                    TraverseParms.For(
                        getter,
                        Danger.Deadly,
                        TraverseMode.ByPawn,
                        false),
                    9999f,
                    validator.ValidateFast);
            }
            else
            {
                //CCL_Log.Message( "Non-humanlike closest reachable..." );
                int searchRegionsMax = 30;
                if (getter.Faction == Faction.OfPlayer)
                {
                    searchRegionsMax = 60;
                }
                potentialFoodSource = GenClosest.ClosestThingReachable(
                    getter.Position,
                    thingRequest,
                    PathEndMode.ClosestTouch,
                    TraverseParms.For(
                        getter,
                        Danger.Deadly,
                        TraverseMode.ByPawn,
                        false),
                    9999f,
                    validator.Validate,
                    null,
                    searchRegionsMax,
                    false);
                if (potentialFoodSource == null)
                {
                    //CCL_Log.Message( "Non-humanlike closest reachable desperate..." );
                    validator.desperate = true;
                    potentialFoodSource = GenClosest.ClosestThingReachable(
                        getter.Position,
                        thingRequest,
                        PathEndMode.ClosestTouch,
                        TraverseParms.For(
                            getter,
                            Danger.Deadly,
                            TraverseMode.ByPawn,
                            false),
                        9999f,
                        validator.ValidateFast,
                        null,
                        searchRegionsMax,
                        false);
                }
            }
            Profiler.EndSample();
            //CCL_Log.Message( string.Format( "{0} picked {1} for {2}", getter.LabelShort, potentialFoodSource == null ? "nothing" : potentialFoodSource.ThingID, eater.LabelShort ) );
            return(potentialFoodSource);
        }