static void _DebugFoodSearchFromMouse_OnGUI() { IntVec3 a = Verse.UI.MouseCell(); bestFoodSourceFromMouse = null; bestFoodSource = null; // ------------------------------------------------------------------------------ pawnA = null; pawnB = null; var pawnSelection = Find.Selector.SelectedObjects.Where(arg => arg is Pawn).Cast <Pawn>(); pawnA = pawnSelection.FirstOrDefault(); if (pawnSelection.Count() == 2) { pawnB = pawnSelection.ElementAt(1); } if (pawnB != null && pawnA != null && (pawnA.Faction != pawnB.Faction || RimWorld.FoodUtility.ShouldBeFedBySomeone(pawnA) || RimWorld.FoodUtility.ShouldBeFedBySomeone(pawnB))) { //TODO: watch out for compatibility if (pawnA.IsColonist) { eater = pawnB; getter = pawnA; } else if (pawnB.IsColonist) { eater = pawnA; getter = pawnB; } else { eater = getter = pawnA; } } else { eater = getter = pawnA; } // ------------------------------------------------------------------------------ if (eater == null) { return; } if (eater.Map != Find.VisibleMap) { return; } Text.Anchor = TextAnchor.MiddleCenter; Text.Font = GameFont.Tiny; var policy = eater.GetPolicyAssignedTo(); var thingAtCursorCell = Find.VisibleMap.thingGrid.ThingsAt(a).FirstOrDefault(delegate(Thing t) { var category = t.GetFoodCategory(); if (category == FoodCategory.Null) { return(false); } return(FoodUtility.IsValidFoodSourceForPawn(t, eater, getter, policy, false)); }); ThingDef dum2; // Generates cache var foundFood = FoodUtility.TryFindBestFoodSourceFor(getter, eater, true, out bestFoodSource, out dum2); if (!foundFood) { //goto cursorwidget; return; } // ------------------------------------------------------------------------------ List <FoodSourceRating> foodsToDisplay; var selectedFoods = Find.Selector.SelectedObjects .Where(arg => (arg is Thing) && (arg as Thing).DetermineFoodCategory() != FoodCategory.Null) .Cast <Thing>().ToList(); FoodSearchCache.PawnEntry pawnEntry; //IEnumerable<Thing> foodList = //TODO: no score shown with unrestricted policies if (getter.isWildAnimal() || policy.unrestricted || !FoodSearchCache.TryGetEntryForPawn(getter, eater, out pawnEntry, true)) { return; } foodsToDisplay = pawnEntry.AllRankedFoods .OrderBy(arg => (a - arg.FoodSource.Position).LengthManhattan).ToList() .GetRange(0, Math.Min(300, pawnEntry.AllRankedFoods.Count)); //bool advancedInfoForAll; //if (!selectedFoods.Any()) //{ // selectedFoods.Add(bestFoodSource); // selectedFoods.Add(foodList.AllRankedFoods.MinBy((arg) => (a - arg.FoodSource.Position).LengthHorizontal).FoodSource); // advancedInfoForAll = false; //} //else // advancedInfoForAll = true; bool advancedInfoForAll = ModCore.drawFoodSearchMode == ModCore.DrawFoodSearchMode.Advanced; // ----------------------- Recalculate food source rating distance factors ------------------------------ FoodSourceRating bestScoreFromMouse = null; for (int i = 0; i < foodsToDisplay.Count; i++) { var current = foodsToDisplay[i]; foodsToDisplay[i] = new FoodSourceRating(foodsToDisplay[i]); foodsToDisplay[i].SetComp("Distance", -(a - current.FoodSource.Position).LengthManhattan * policy.distanceFactor); } //bestScoreFromMouse = foodsToDisplay.MaxBy((arg) => arg.Score); bestScoreFromMouse = foodsToDisplay.MaxBy((arg) => arg.ScoreForceSum); bestFoodSourceFromMouse = bestScoreFromMouse.FoodSource; // ----------------------- Food sources widgets ------------------------------ foreach (var current in foodsToDisplay) { //float score = current.Score; Vector2 vector = current.FoodSource.DrawPos.MapToUIPosition(); //Rect rect = new Rect(vector.x - 100f, vector.y - 100f, 200f, 200f); Rect rect = new Rect(vector.x, vector.y, 200f, 200f); if (getter.inventory == null || !getter.inventory.innerContainer.Contains(current.FoodSource)) { bool advancedInfo = (advancedInfoForAll); Color widgetColor; if (current == bestScoreFromMouse || current.FoodSource == bestFoodSource || current.FoodSource == thingAtCursorCell) { if (ModCore.drawFoodSearchMode == ModCore.DrawFoodSearchMode.AdvancedForBest) { advancedInfo = true; } if (current.FoodSource == thingAtCursorCell) { widgetColor = Color.green; } else { widgetColor = Resources.Color.Orange; } } else { widgetColor = Color.white; } string text = current.ToWidgetString(advancedInfo, current.FoodSource.DetermineFoodCategory()); #if DEBUG if (current.FoodSource is Pawn) { text += "\n" + "ratio1=" + FoodUtility.GetPreyRatio1(getter, current.FoodSource as Pawn); text += "\n" + "ratio2=" + FoodUtility.GetPreyRatio2(getter, current.FoodSource as Pawn); } #endif Text.Anchor = TextAnchor.UpperLeft; { var backup = GUI.color; GUI.color = widgetColor; Widgets.Label(rect, text); GUI.color = backup; } } } // ----------------------- Cursor widget ----------------------- //TODO: cursor widget not drawn when no food found string pawninfo; pawninfo = string.Format("{0}", getter.NameStringShort); if (getter != eater) { pawninfo += string.Format(" (gives to) {0}", eater.NameStringShort); } //pawninfo += string.Format(" ---> {4} ({6:F0}){5}\nFood need: {1:F1} / {2:F1}\nPolicy: {3}", // eater.NameStringShort, //eater.needs.food.CurLevel, //eater.needs.food.MaxLevel, //policy != null ? policy.label : "(no policy)", //bestFoodSourceFromMouse != null ? bestFoodSourceFromMouse.Label : "(no reachable food)", //(bestFoodSourceFromMouse != null && getter.inventory != null && getter.inventory.innerContainer.Contains(bestFoodSourceFromMouse)) ? " (inventory)" : "", //bestScoreFromMouse.Score); { string score; string foodname; if (bestFoodSourceFromMouse != null) { foodname = bestFoodSourceFromMouse.Label; score = bestScoreFromMouse.ScoreForceSum.ToString("F0"); } else { foodname = "(no reachable food)"; score = ""; } pawninfo += " ---> " + foodname + " (" + score + ")" + "\n"; pawninfo += "Food need: " + eater.needs.food.CurLevel.ToString("F1") + " / " + eater.needs.food.MaxLevel.ToString("F1") + "\n"; pawninfo += "Policy: " + (policy != null ? policy.label : "(no policy)") + "\n"; } Text.Anchor = TextAnchor.UpperLeft; //TODO: spread or merge widgets + Widgets.Label(new Rect((a.ToUIPosition() + new Vector2(-100f, -80f)), new Vector2(200f, 200f)), pawninfo); }
internal static bool Internal(Pawn getter, Pawn eater, bool desperate, out Thing foodSource, out ThingDef foodDef, bool canRefillDispenser = true, bool canUseInventory = true, bool allowForbidden = false, bool allowCorpse = true, Policy forcedPolicy = null) { List <FoodSourceRating> FoodListForPawn; FoodSearchCache.PawnEntry pawnEntry; if (!FoodSearchCache.TryGetEntryForPawn(getter, eater, out pawnEntry, allowForbidden)) { Policy policy; if (forcedPolicy != null) { policy = forcedPolicy; } else { policy = PolicyUtils.GetPolicyAssignedTo(eater, getter); } bool foundFood = FoodUtils.MakeRatedFoodListForPawn(getter.Map, eater, getter, policy, out FoodListForPawn, canUseInventory, allowForbidden); pawnEntry = FoodSearchCache.AddPawnEntry(getter, eater, FoodListForPawn); } bool flagAllowHunt = (getter == eater && eater.RaceProps.predator && !eater.health.hediffSet.HasTendableInjury()); bool flagAllowPlant = (getter == eater); // C# 5 :'( var foodSourceRating = pawnEntry.GetBestFoodEntry(flagAllowPlant, allowCorpse, flagAllowHunt); if (foodSourceRating != null) { foodSource = foodSourceRating.FoodSource; } else { foodSource = null; } if (foodSource == null) // ** If no food source is found set food Definition to null and return { foodDef = null; return(false); } foodDef = RimWorld.FoodUtility.GetFinalIngestibleDef(foodSource); // ** Set food definition of food source and return return(true); //bool flag = getter.RaceProps.ToolUser && getter.health.capacities.CapableOf(PawnCapacityDefOf.Manipulation); //Thing thing = null; //if (canUseInventory) //{ // if (flag) // { // thing = RimWorld.FoodUtility.BestFoodInInventory(getter, null, FoodPreferability.MealAwful, FoodPreferability.MealLavish, 0f, false); // } // if (thing != null) // { // if (getter.Faction != Faction.OfPlayer) // { // foodSource = thing; // foodDef = RimWorld.FoodUtility.GetFinalIngestibleDef(foodSource); // return true; // } // CompRottable compRottable = thing.TryGetComp<CompRottable>(); // if (compRottable != null && compRottable.Stage == RotStage.Fresh && compRottable.TicksUntilRotAtCurrentTemp < 30000) // { // foodSource = thing; // foodDef = RimWorld.FoodUtility.GetFinalIngestibleDef(foodSource); // return true; // } // } //} //bool allowPlant = getter == eater; }
// RimWorld.FoodUtility private static bool _TryFindBestFoodSourceFor(Pawn getter, Pawn eater, bool desperate, out Thing foodSource, out ThingDef foodDef, bool canRefillDispenser = true, bool canUseInventory = true, bool allowForbidden = false, bool allowCorpse = true, Policy forcedPolicy = null) { #if DEBUG Log.Message("_TryFindBestFoodSourceFor() getter=" + getter + " eater=" + eater + " desperate=" + desperate + " canUseInventory=" + canUseInventory + " allowForbidden=" + allowForbidden); #endif Policy policy; //taming ? TODO: check for bug free if (forcedPolicy != null) { policy = forcedPolicy; } else { policy = eater.GetPolicyAssignedTo(getter); } if (getter.isWildAnimal() || getter.isInsectFaction() || policy.unrestricted || getter.InMentalState || Config.ControlDisabledForPawn(eater)) { return(Original.FoodUtility.TryFindBestFoodSourceFor(getter, eater, desperate, out foodSource, out foodDef, canRefillDispenser, canUseInventory, allowForbidden, allowCorpse)); } List <FoodSourceRating> FoodListForPawn; FoodSearchCache.PawnEntry pawnEntry; if (!FoodSearchCache.TryGetEntryForPawn(getter, eater, out pawnEntry, allowForbidden)) { bool foundFood = MakeRatedFoodListForPawn(getter.Map, eater, getter, policy, out FoodListForPawn, canUseInventory, allowForbidden); pawnEntry = FoodSearchCache.AddPawnEntry(getter, eater, FoodListForPawn); } bool flagAllowHunt = (getter == eater && eater.RaceProps.predator && !eater.health.hediffSet.HasTendableInjury()); bool flagAllowPlant = (getter == eater); // C# 5 :'( var foodSourceRating = pawnEntry.GetBestFoodEntry(flagAllowPlant, allowCorpse, flagAllowHunt); if (foodSourceRating != null) { foodSource = foodSourceRating.FoodSource; } else { foodSource = null; } if (foodSource == null) { foodDef = null; return(false); } foodDef = RimWorld.FoodUtility.GetFinalIngestibleDef(foodSource); return(true); //bool flag = getter.RaceProps.ToolUser && getter.health.capacities.CapableOf(PawnCapacityDefOf.Manipulation); //Thing thing = null; //if (canUseInventory) //{ // if (flag) // { // thing = RimWorld.FoodUtility.BestFoodInInventory(getter, null, FoodPreferability.MealAwful, FoodPreferability.MealLavish, 0f, false); // } // if (thing != null) // { // if (getter.Faction != Faction.OfPlayer) // { // foodSource = thing; // foodDef = RimWorld.FoodUtility.GetFinalIngestibleDef(foodSource); // return true; // } // CompRottable compRottable = thing.TryGetComp<CompRottable>(); // if (compRottable != null && compRottable.Stage == RotStage.Fresh && compRottable.TicksUntilRotAtCurrentTemp < 30000) // { // foodSource = thing; // foodDef = RimWorld.FoodUtility.GetFinalIngestibleDef(foodSource); // return true; // } // } //} //bool allowPlant = getter == eater; }