Пример #1
0
        internal static bool IsValidFoodSourceForPawn(this Thing food, Pawn eater, Pawn getter, Policy policy, bool allowForbidden)
        {
            try
            {
                bool canManipulate = getter.RaceProps.ToolUser && getter.health.capacities.CapableOf(PawnCapacityDefOf.Manipulation);

                bool inventory = (getter.inventory != null && getter.inventory.innerContainer.Contains(food));

                if (!(food != null &&
                      (inventory || food.Spawned) &&
                      !food.Destroyed &&
                      (allowForbidden || !food.IsForbidden(getter)) &&
                      (!food.def.IsIngestible || food.IngestibleNow) &&
                      (inventory || food.IsSociallyProper(eater) || food.IsSociallyProper(getter)) &&
                      //TODO: eater == getter ?
                      getter.CanReachFoodSource(food) &&
                      (inventory || getter.CanReserve(food))
                      ))
                {
                    return(false);
                }

                if (food is Pawn)
                {
                    if (((Pawn)food).RaceProps.Humanlike ||
                        food.Map.designationManager.AllDesignationsOn(food).Any(arg => arg.def == DesignationDefOf.Tame) ||
                        !FoodUtils.IsAcceptablePreyFor(eater, food as Pawn) ||
                        !policy.PolicyAllows(FoodCategory.Hunt) ||
                        Utils.IsAnyoneCapturing(food.Map, food as Pawn)                         // redundant with humanlike ?
                        )
                    {
                        return(false);
                    }
                }
                else
                {
                    var category = food.DetermineFoodCategory();
                    if (!eater.RaceProps.CanEverEat((food is Building_NutrientPasteDispenser) ? ((Building_NutrientPasteDispenser)food).DispensableDef : food.def) ||
                        ((food is Building_NutrientPasteDispenser) && (!((Building_NutrientPasteDispenser)food).CanDispenseNow || !canManipulate)) ||
                        !policy.PolicyAllows(category) ||
                        category == FoodCategory.Ignore ||
                        category == FoodCategory.Luxury)
                    {
                        return(false);
                    }

                    //TODO: plant pot avoidance not tested
                    if (food.def.plant != null && food.Position.GetThingList(food.Map).Any((obj) => obj.def == ThingDef.Named("PlantPot")))
                    {
                        return(false);
                    }
                }

                return(true);
            }
            catch (Exception ex)
            {
                throw new Exception(string.Format("food={0} eater={1} policy={2}", food, eater, policy), ex);
            }
        }
Пример #2
0
        void MakeDietForRace(ThingDef def, Policy policy)
        {
            if (policy.unrestricted)
            {
                return;
            }

            elements = policy.baseDiet.ToList();

            if (!def.race.Eats(FoodTypeFlags.Corpse))
            {
                RemoveCategory(FoodCategory.Corpse);
                RemoveCategory(FoodCategory.InsectCorpse);
                RemoveCategory(FoodCategory.HumanlikeCorpse);
                RemoveCategory(FoodCategory.Hunt);
            }
            else if (!def.race.predator)
            {
                RemoveCategory(FoodCategory.Hunt);
            }

            FoodCategory[] huntCat = { FoodCategory.Hunt };

            var nonHuntCategories = elements.Where((DietElement arg) => !huntCat.Contains(arg.foodCategory)).ToArray();

            foreach (var current in nonHuntCategories)
            {
                if (policy.PolicyAllows(current.foodCategory))
                {
                    if (!DefDatabaseHelper.AllDefsIngestibleNAnimals.Where((arg) => arg.ingestible != null && arg.DetermineFoodCategory(true) == current.foodCategory).Any((arg) => def.race.CanEverEat(arg)))
                    {
                        RemoveCategory(current.foodCategory);
                    }
                }
            }

            float num = 0;

            foreach (var current in elements)
            {
                //TODO: fix broken diet order when removing the first element for a race (eg: thrumbo)
                current.totalOffsetValue = num;
                num += current.scoreOffset;
            }
        }
Пример #3
0
        internal static bool MakeRatedFoodListForPawn(Map map, Pawn eater, Pawn getter, Policy policy, out List <FoodSourceRating> foodList, bool canUseInventory, bool allowForbidden)
        {
#if DEBUG
            Log.Message("MakeRatedFoodListForPawn() eater=" + eater + " getter=" + getter + " canuseinventory=" + canUseInventory);
#endif

            Func <Thing, bool> FoodValidator = (arg => IsValidFoodSourceForPawn(arg, eater, getter, policy, allowForbidden));

            var diet = policy.GetDietForPawn(eater);

            //foreach (var item in policy.PerRacesDiet[eater.def].elements)
            //{
            //	FoodCategoryUtils.FoodRecords[item
            //	var foodsOfCategory = ite
            //}

            // ------------------------------------------------------------------------------------------------
            ThingRequestGroup thingRequest;

            //TODO: detour ThingsLister
            if (!policy.PerRacesDiet[eater.def].ContainsElement(FoodCategory.Grass) &&
                !policy.PerRacesDiet[eater.def].ContainsElement(FoodCategory.Hay))
            {
                thingRequest = ThingRequestGroup.FoodSourceNotPlantOrTree;
            }
            else
            {
                thingRequest = ThingRequestGroup.FoodSource;
            }

            List <Thing> searchSet = map.listerThings.ThingsInGroup(thingRequest).Where(FoodValidator).ToList();

            // TODO: Limits the number of searched by category
            if (searchSet.Count >= Config.FoodSearchMaxItemsCount)
            {
#if DEBUG
                int num = searchSet.Count;
#endif

                var newsearchSet = searchSet.OrderBy((arg) => (arg.Position - getter.Position).LengthManhattan).ToList();
                searchSet = newsearchSet.GetRange(0, Math.Min(newsearchSet.Count, Config.FoodSearchMaxItemsCount));

#if DEBUG
                Log.Message(string.Format("MakeRatedFoodListForPawn(): too many items, reduced from {0} to {1}", num, searchSet.Count));
#endif

                //var newsearchSet = new List<Thing>();
                //var categoriesList = from entry in searchSet
                //					 group entry by entry.def;
                //foreach (var group in categoriesList)
                //{
                //	if (group.Count() > 500)
                //	{
                //		var list = group.OrderByDescending((arg) => (arg.Position - getter.Position).LengthManhattan);
                //	}
                //}
            }

            if (eater == getter && eater.RaceProps.predator && policy.PolicyAllows(FoodCategory.Hunt))
            {
                IEnumerable <Thing> allPawnsSpawned = eater.Map.mapPawns.AllPawnsSpawned
                                                      .Cast <Thing>()
                                                      //.Select(arg => arg as Thing)
                                                      .Where(FoodValidator);

                searchSet.AddRange(allPawnsSpawned);
            }

            if (canUseInventory && getter.RaceProps.ToolUser && getter.health.capacities.CapableOf(PawnCapacityDefOf.Manipulation) && getter.inventory != null)
            {
                var inventoryFood = getter.inventory.innerContainer.Where(arg => arg.def.IsIngestible).Where(FoodValidator);
                searchSet.AddRange(inventoryFood);

#if DEBUG
                Log.Message(string.Format("MakeRatedFoodListForPawn() eater={0} getter={1} got {2}/{3} things from inventory", eater, getter, inventoryFood.Count(), getter.inventory.innerContainer.Count));
#endif
            }

            foodList = MakeRatedFoodListFromThingList(searchSet, eater, getter, policy);

#if DEBUG
            var foodListInventory = foodList.Where(arg => getter.inventory.innerContainer.Contains(arg.FoodSource));

            var inventoryScoreText = "Inventory:";

            foreach (var item in foodListInventory)
            {
                inventoryScoreText += "\n-------------\n" + item.ToWidgetString(true, item.DefRecord.category);
            }

            Log.Message(inventoryScoreText);
#endif

            if (!foodList.Any())
            {
                return(false);
            }

            return(true);
        }