public FoodSourceRating(FoodSourceRating obj)
        {
            Score      = 0f;
            FoodSource = obj.FoodSource;
            DefRecord  = obj.DefRecord;
            ScoreComps = new List <Component>();

            foreach (var item in obj.ScoreComps)
            {
                AddComp(item.Name, item.Value, item.Hidden);
            }
        }
Exemplo n.º 2
0
        //TODO: optimize function
        internal static FoodSourceRating FoodScoreFor(Policy policy, Pawn eater, Pawn getter, Thing food, bool noDistanceFactor = false, bool quickScore = false)
        {
            var obj = new FoodSourceRating();

            obj.FoodSource = food;
            obj.DefRecord  = food.GetFoodDefRecord();

            // ------ Distance factor ------

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

            if (!noDistanceFactor)
            {
                float distanceFactor;
                if (inInventory)
                {
                    distanceFactor = 0f;
                }
                else
                {
                    distanceFactor = -((food.Position - eater.Position).LengthManhattan) * policy.distanceFactor;
                }

                obj.AddComp("Distance", distanceFactor);
            }

            if (inInventory && getter == eater && food.def.ingestible.preferability >= FoodPreferability.MealAwful)
            {
                obj.AddComp("Inventory", 500f);
            }

            // ------------- Policy food category factor -------------

            //if (!policy.unrestricted)
            //	obj.AddComp(food.DetermineFoodCategory().ToString(), policy.GetFoodScoreOffset(eater, food));

            // ------------- Prey score factor -------------

            const float PREY_FACTOR_MULTIPLIER = 5f;                     //Because the vanilla prey factor is fairly weak.

            {
                if (food is Pawn)
                {
                    var preyScore = RimWorld.FoodUtility.GetPreyScoreFor(eater, food as Pawn) * PREY_FACTOR_MULTIPLIER;
                    //ducktape, negates the distance factor of the vanilla function as it is already calculated by the mod.
                    preyScore += (eater.Position - food.Position).LengthHorizontal * PREY_FACTOR_MULTIPLIER;
                    obj.AddComp("Prey (ratio=" + Detours.FoodUtility.GetPreyRatio(eater, food as Pawn).ToString("F2") + ")", preyScore);
                    return(obj);
                }
            }

            // ------------- Food def optimality offset -------------

            if (policy.optimalityOffsetMatters && food.def.ingestible != null)
            {
                obj.AddComp("Def", food.def.ingestible.optimalityOffset);
            }

            if (!quickScore)
            {
                // ------------- Mood effect factor -------------

                //float num2 = 0f;
                if (eater.needs != null && eater.needs.mood != null && policy.moodEffectMatters)
                {
                    List <ThoughtDef> list;

                    if (!(food is RimWorld.Building_NutrientPasteDispenser))
                    {
                        list = RimWorld.FoodUtility.ThoughtsFromIngesting(eater, food);
                    }
                    else
                    {
                        list = ((RimWorld.Building_NutrientPasteDispenser)food).GetBestMealThoughtsFor(eater);
                    }

                    for (int i = 0; i < list.Count; i++)
                    {
                        obj.AddComp(list[i].defName,
                                    policy.moodEffectFactor * Detours.Original.FoodUtility.FoodOptimalityEffectFromMoodCurve.Evaluate(list[i].stages[0].baseMoodEffect));
                    }
                }

                // ------------- Cost factor (waste factor aswell) -------------

                float costRatio;
                float foodNutrition;
                var   curFoodLevel = eater.needs.food.CurLevel;
                var   maxFoodLevel = eater.needs.food.MaxLevel;

                if (food.def.IsFoodDispenser)
                {
                    foodNutrition = ThingDefOf.MealNutrientPaste.ingestible.nutrition;
                }
                else if (food.def.IsCorpse)
                {
                    var corpse = food as Corpse;
                    foodNutrition = RimWorld.FoodUtility.GetBodyPartNutrition(corpse.InnerPawn, corpse.GetBestBodyPartToEat(eater, curFoodLevel));
                }
                else
                {
                    foodNutrition = food.def.ingestible.nutrition;
                }

                if (foodNutrition >= 0.1f)
                {
                    //TODO: ajust; add record for the NPD

                    if (food is RimWorld.Building_NutrientPasteDispenser)
                    {
                        costRatio = (food.def.building.foodCostPerDispense * 0.05f) / ThingDefOf.MealNutrientPaste.ingestible.nutrition;
                    }
                    else
                    {
                        costRatio = (obj.DefRecord.costFactor);
                    }

                    //TODO: combine waste & cost factors

                    float actualMealCost   = costRatio * foodNutrition;
                    float costFactorOffset = Math.Max(0, actualMealCost - (maxFoodLevel - curFoodLevel)) * -Config.CostFactor /* * policy.costFactorMultiplier*/;
                    //* Config.CostFactor * policy.costFactorMultiplier;

                    if (costFactorOffset != 0f)
                    {
                        obj.AddComp("Hunger (min=" + actualMealCost.ToString("F2") + ")", costFactorOffset);
                    }
                }


                // ------------- TODO: Rot factor -------------
            }

            return(obj);
        }
Exemplo n.º 3
0
		//TODO: optimize function
		internal static FoodSourceRating FoodScoreFor(Policy policy, Pawn eater, Pawn getter, Thing food, bool noDistanceFactor = false, bool quickScore = false)
		{
			var obj = new FoodSourceRating();

			obj.FoodSource = food;
			obj.DefRecord = food.GetFoodDefRecord();

			// ------ Distance factor ------ 

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

			if (!noDistanceFactor)
			{
				float distanceFactor;
				if (inInventory)
					distanceFactor = 0f;
				else
					distanceFactor = -((food.Position - eater.Position).LengthManhattan) * policy.distanceFactor;

				obj.AddComp("Distance", distanceFactor);
			}

			if (inInventory && getter == eater && food.def.ingestible.preferability >= FoodPreferability.MealAwful)
			{
				obj.AddComp("Inventory", 500f);
			}

			// ------------- Policy food category factor -------------

			//if (!policy.unrestricted)
			//	obj.AddComp(food.DetermineFoodCategory().ToString(), policy.GetFoodScoreOffset(eater, food));

			// ------------- Prey score factor -------------

			const float PREY_FACTOR_MULTIPLIER = 5f; //Because the vanilla prey factor is fairly weak.

			{
				if (food is Pawn)
				{
					var preyScore = RimWorld.FoodUtility.GetPreyScoreFor(eater, food as Pawn) * PREY_FACTOR_MULTIPLIER;
					//ducktape, negates the distance factor of the vanilla function as it is already calculated by the mod.
					preyScore += (eater.Position - food.Position).LengthHorizontal * PREY_FACTOR_MULTIPLIER;
					obj.AddComp("Prey (ratio=" + FoodUtils.GetPreyRatio(eater, food as Pawn).ToString("F2") + ")", preyScore);
					return obj;
				}
			}

			// ------------- Food def optimality offset -------------

			if (policy.optimalityOffsetMatters && food.def.ingestible != null)
			{
				obj.AddComp("Def", food.def.ingestible.optimalityOffset);
			}

			if (!quickScore)
			{
				// ------------- Mood effect factor -------------

				//float num2 = 0f;
				if (eater.needs != null && eater.needs.mood != null && policy.moodEffectMatters)
				{
					List<ThoughtDef> list;

					if (!(food is RimWorld.Building_NutrientPasteDispenser))
						list = RimWorld.FoodUtility.ThoughtsFromIngesting(eater, food);
					else
						list = ((RimWorld.Building_NutrientPasteDispenser)food).GetBestMealThoughtsFor(eater);

					for (int i = 0; i < list.Count; i++)
					{
						obj.AddComp(list[i].defName,
									policy.moodEffectFactor * Detours.Access.FoodOptimalityEffectFromMoodCurve.Evaluate(list[i].stages[0].baseMoodEffect));
					}
				}

				// ------------- Cost factor (waste factor aswell) -------------

				//TODO: concurrent based waste factor.

				float costRatio;
				float foodNutrition;
				var curFoodLevel = eater.needs.food.CurLevel;
				var maxFoodLevel = eater.needs.food.MaxLevel;

				if (food.def.IsFoodDispenser)
					foodNutrition = ThingDefOf.MealNutrientPaste.ingestible.nutrition;
				else if (food.def.IsCorpse)
				{
					var corpse = food as Corpse;
					BodyPartRecord part = corpse.GetBestBodyPartToEat(eater, curFoodLevel));
					if (part != null)
						foodNutrition = RimWorld.FoodUtility.GetBodyPartNutrition(corpse.InnerPawn, part);
				}
				else
					foodNutrition = food.def.ingestible.nutrition;

				if (foodNutrition >= 0.1f)
				{
					//TODO: ajust; add record for the NPD

					if (food is RimWorld.Building_NutrientPasteDispenser)
						costRatio = (food.def.building.nutritionCostPerDispense * 0.05f) / ThingDefOf.MealNutrientPaste.ingestible.nutrition;
					else
						costRatio = (obj.DefRecord.costFactor);

					if (food.def.IsCorpse)
						costRatio *= 0.25f;

					//TODO: combine waste & cost factors

					float actualMealCost = costRatio * foodNutrition;
					float costFactorOffset = Math.Max(0, actualMealCost - (maxFoodLevel - curFoodLevel)) * -Config.CostFactor /* * policy.costFactorMultiplier*/;
					//float costFactorOffset =  (actualMealCost - (maxFoodLevel - curFoodLevel)) * -Config.CostFactor /* * policy.costFactorMultiplier*/;
					//* Config.CostFactor * policy.costFactorMultiplier;

					if (costFactorOffset != 0f)
						obj.AddComp("Hunger/Cost (min=" + actualMealCost.ToString("F2") + ")", costFactorOffset);
				}


				// ------------- TODO: Rot factor -------------

				var compRottable = food.TryGetComp<CompRottable>();

				if (compRottable != null)
				{
					var ticksUntilRotAtCurrentTemp = compRottable.TicksUntilRotAtCurrentTemp;
					const int V = 30000;
					if (ticksUntilRotAtCurrentTemp < V)
					{
						obj.AddComp("Rotting soon", Config.RottingScoreFactor / (ticksUntilRotAtCurrentTemp - V));
					}
					else
					{
						var daysToRotStart = GenDate.TicksToDays(ticksUntilRotAtCurrentTemp);
						if (daysToRotStart >= 40)
						{
							obj.AddComp("Rots in " + daysToRotStart.ToString("####") + " days.", -Mathf.Min(Config.UnrottableFoodScoreOffset * 0.7f, Mathf.Log((1 + daysToRotStart)) * 20));
						}
					}
				}
				else
				{
					obj.AddComp("Never rots", -Config.UnrottableFoodScoreOffset);
				}
			}

			return obj;
		}