Beispiel #1
0
        private void TrySatisfyFoodNeed(Pawn pawn, Need_Food food)
        {
            if (food.CurCategory < HungerCategory.Hungry)
            {
                return;
            }
            if (VirtualPlantsUtility.CanEatVirtualPlantsNow(pawn))
            {
                VirtualPlantsUtility.EatVirtualPlants(pawn);
                return;
            }
            Thing thing;
            Pawn  pawn2;

            if (CaravanInventoryUtility.TryGetBestFood(this.caravan, pawn, out thing, out pawn2))
            {
                food.CurLevel += thing.Ingested(pawn, food.NutritionWanted);
                if (thing.Destroyed)
                {
                    if (pawn2 != null)
                    {
                        pawn2.inventory.innerContainer.Remove(thing);
                        this.caravan.RecacheImmobilizedNow();
                        this.caravan.RecacheDaysWorthOfFood();
                    }
                    if (!this.caravan.notifiedOutOfFood && !CaravanInventoryUtility.TryGetBestFood(this.caravan, pawn, out thing, out pawn2))
                    {
                        Messages.Message("MessageCaravanRanOutOfFood".Translate(this.caravan.LabelCap, pawn.Label, pawn.Named("PAWN")), this.caravan, MessageTypeDefOf.ThreatBig, true);
                        this.caravan.notifiedOutOfFood = true;
                    }
                }
            }
        }
Beispiel #2
0
 private void TrySatisfyFoodNeed(Pawn pawn, Need_Food food)
 {
     if ((int)food.CurCategory >= 1)
     {
         Thing food2;
         Pawn  owner;
         if (VirtualPlantsUtility.CanEatVirtualPlantsNow(pawn))
         {
             VirtualPlantsUtility.EatVirtualPlants(pawn);
         }
         else if (CaravanInventoryUtility.TryGetBestFood(caravan, pawn, out food2, out owner))
         {
             food.CurLevel += food2.Ingested(pawn, food.NutritionWanted);
             if (food2.Destroyed)
             {
                 if (owner != null)
                 {
                     owner.inventory.innerContainer.Remove(food2);
                     caravan.RecacheImmobilizedNow();
                     caravan.RecacheDaysWorthOfFood();
                 }
                 if (!caravan.notifiedOutOfFood && !CaravanInventoryUtility.TryGetBestFood(caravan, pawn, out food2, out owner))
                 {
                     Messages.Message("MessageCaravanRanOutOfFood".Translate(caravan.LabelCap, pawn.Label, pawn.Named("PAWN")), caravan, MessageTypeDefOf.ThreatBig);
                     caravan.notifiedOutOfFood = true;
                 }
             }
         }
     }
 }
Beispiel #3
0
        private string GetTileTip(int tile, int pathIndex)
        {
            int           num           = paths[pathIndex].NodesReversed.IndexOf(tile);
            int           num2          = (num > 0) ? paths[pathIndex].NodesReversed[num - 1] : ((pathIndex >= paths.Count - 1 || paths[pathIndex + 1].NodesReversed.Count < 2) ? (-1) : paths[pathIndex + 1].NodesReversed[paths[pathIndex + 1].NodesReversed.Count - 2]);
            int           num3          = cachedTicksToWaypoint[pathIndex] + CaravanArrivalTimeEstimator.EstimatedTicksToArrive(paths[pathIndex].FirstNode, tile, paths[pathIndex], 0f, CaravanTicksPerMove, GenTicks.TicksAbs + cachedTicksToWaypoint[pathIndex]);
            int           num4          = GenTicks.TicksAbs + num3;
            StringBuilder stringBuilder = new StringBuilder();

            if (num3 != 0)
            {
                stringBuilder.AppendLine("EstimatedTimeToTile".Translate(num3.ToStringTicksToDays("0.##")));
            }
            stringBuilder.AppendLine("ForagedFoodAmount".Translate() + ": " + Find.WorldGrid[tile].biome.forageability.ToStringPercent());
            stringBuilder.Append(VirtualPlantsUtility.GetVirtualPlantsStatusExplanationAt(tile, num4));
            if (num2 != -1)
            {
                stringBuilder.AppendLine();
                stringBuilder.AppendLine();
                StringBuilder stringBuilder2 = new StringBuilder();
                float         num5           = WorldPathGrid.CalculatedMovementDifficultyAt(num2, perceivedStatic: false, num4, stringBuilder2);
                float         roadMovementDifficultyMultiplier = Find.WorldGrid.GetRoadMovementDifficultyMultiplier(tile, num2, stringBuilder2);
                stringBuilder.Append("TileMovementDifficulty".Translate() + ":\n" + stringBuilder2.ToString().Indented("  "));
                stringBuilder.AppendLine();
                stringBuilder.Append("  = ");
                stringBuilder.Append((num5 * roadMovementDifficultyMultiplier).ToString("0.#"));
            }
            return(stringBuilder.ToString());
        }
Beispiel #4
0
        public static string GetVirtualPlantsStatusExplanationAt(int tile, int ticksAbs)
        {
            StringBuilder stringBuilder = new StringBuilder();

            if (ticksAbs == GenTicks.TicksAbs)
            {
                stringBuilder.Append("AnimalsCanGrazeNow".Translate());
            }
            else if (ticksAbs > GenTicks.TicksAbs)
            {
                stringBuilder.Append("AnimalsWillBeAbleToGraze".Translate());
            }
            else
            {
                stringBuilder.Append("AnimalsCanGraze".Translate());
            }
            stringBuilder.Append(": ");
            bool flag = VirtualPlantsUtility.EnvironmentAllowsEatingVirtualPlantsAt(tile, ticksAbs);

            stringBuilder.Append((!flag) ? "No".Translate() : "Yes".Translate());
            if (flag)
            {
                float?approxDaysUntilPossibleToGraze = VirtualPlantsUtility.GetApproxDaysUntilPossibleToGraze(tile, ticksAbs, true);
                if (approxDaysUntilPossibleToGraze != null)
                {
                    stringBuilder.Append("\n" + "PossibleToGrazeFor".Translate(new object[]
                    {
                        approxDaysUntilPossibleToGraze.Value.ToString("0.#")
                    }));
                }
                else
                {
                    stringBuilder.Append("\n" + "PossibleToGrazeForever".Translate());
                }
            }
            else
            {
                if (!Find.WorldGrid[tile].biome.hasVirtualPlants)
                {
                    stringBuilder.Append("\n" + "CantGrazeBecauseOfBiome".Translate(new object[]
                    {
                        Find.WorldGrid[tile].biome.label
                    }));
                }
                float?approxDaysUntilPossibleToGraze2 = VirtualPlantsUtility.GetApproxDaysUntilPossibleToGraze(tile, ticksAbs, false);
                if (approxDaysUntilPossibleToGraze2 != null)
                {
                    stringBuilder.Append("\n" + "CantGrazeBecauseOfTemp".Translate(new object[]
                    {
                        approxDaysUntilPossibleToGraze2.Value.ToString("0.#")
                    }));
                }
            }
            return(stringBuilder.ToString());
        }
 private static bool AnyNonLocalPlantsEatingPawn(List <Pawn> pawns, bool assumeCanEatLocalPlants)
 {
     for (int i = 0; i < pawns.Count; i++)
     {
         if (pawns[i].RaceProps.EatsFood && (!assumeCanEatLocalPlants || !VirtualPlantsUtility.CanEverEatVirtualPlants(pawns[i])))
         {
             return(true);
         }
     }
     return(false);
 }
        public bool AnyPawnOutOfFood(out string malnutritionHediff)
        {
            tmpInvFood.Clear();
            List <Thing> list = CaravanInventoryUtility.AllInventoryItems(caravan);

            for (int i = 0; i < list.Count; i++)
            {
                if (list[i].def.IsNutritionGivingIngestible)
                {
                    tmpInvFood.Add(list[i]);
                }
            }
            List <Pawn> pawnsListForReading = caravan.PawnsListForReading;

            for (int j = 0; j < pawnsListForReading.Count; j++)
            {
                Pawn pawn = pawnsListForReading[j];
                if (!pawn.RaceProps.EatsFood || VirtualPlantsUtility.CanEatVirtualPlantsNow(pawn))
                {
                    continue;
                }
                bool flag = false;
                for (int k = 0; k < tmpInvFood.Count; k++)
                {
                    if (CaravanPawnsNeedsUtility.CanEatForNutritionEver(tmpInvFood[k].def, pawn))
                    {
                        flag = true;
                        break;
                    }
                }
                if (flag)
                {
                    continue;
                }
                int    num  = -1;
                string text = null;
                for (int l = 0; l < pawnsListForReading.Count; l++)
                {
                    Hediff firstHediffOfDef = pawnsListForReading[l].health.hediffSet.GetFirstHediffOfDef(HediffDefOf.Malnutrition);
                    if (firstHediffOfDef != null && (text == null || firstHediffOfDef.CurStageIndex > num))
                    {
                        num  = firstHediffOfDef.CurStageIndex;
                        text = firstHediffOfDef.LabelCap;
                    }
                }
                malnutritionHediff = text;
                tmpInvFood.Clear();
                return(true);
            }
            malnutritionHediff = null;
            tmpInvFood.Clear();
            return(false);
        }
        public static bool AnyPawnOutOfFood(Caravan c, out string malnutritionHediff)
        {
            CaravanPawnsNeedsUtility.tmpInvFood.Clear();
            List <Thing> list = CaravanInventoryUtility.AllInventoryItems(c);

            for (int i = 0; i < list.Count; i++)
            {
                if (list[i].def.IsNutritionGivingIngestible)
                {
                    CaravanPawnsNeedsUtility.tmpInvFood.Add(list[i]);
                }
            }
            List <Pawn> pawnsListForReading = c.PawnsListForReading;

            for (int j = 0; j < pawnsListForReading.Count; j++)
            {
                Pawn pawn = pawnsListForReading[j];
                if (pawn.RaceProps.EatsFood && !VirtualPlantsUtility.CanEatVirtualPlantsNow(pawn))
                {
                    bool flag = false;
                    int  num  = 0;
                    while (num < CaravanPawnsNeedsUtility.tmpInvFood.Count)
                    {
                        if (!CaravanPawnsNeedsUtility.CanEverEatForNutrition(CaravanPawnsNeedsUtility.tmpInvFood[num].def, pawn))
                        {
                            num++;
                            continue;
                        }
                        flag = true;
                        break;
                    }
                    if (!flag)
                    {
                        int    num2 = -1;
                        string text = null;
                        for (int k = 0; k < pawnsListForReading.Count; k++)
                        {
                            Hediff firstHediffOfDef = pawnsListForReading[k].health.hediffSet.GetFirstHediffOfDef(HediffDefOf.Malnutrition, false);
                            if (firstHediffOfDef != null && (text == null || firstHediffOfDef.CurStageIndex > num2))
                            {
                                num2 = firstHediffOfDef.CurStageIndex;
                                text = firstHediffOfDef.LabelCap;
                            }
                        }
                        malnutritionHediff = text;
                        return(true);
                    }
                }
            }
            malnutritionHediff = null;
            return(false);
        }
        public static float?GetApproxDaysUntilPossibleToGraze(int tile, int ticksAbs, bool untilNoLongerPossibleToGraze = false)
        {
            if (!untilNoLongerPossibleToGraze && !Find.WorldGrid[tile].biome.hasVirtualPlants)
            {
                return(null);
            }
            float num = 0f;

            for (int i = 0; i < Mathf.CeilToInt(133.333344f); i++)
            {
                bool flag = VirtualPlantsUtility.EnvironmentAllowsEatingVirtualPlantsAt(tile, ticksAbs + (int)(num * 60000f));
                if ((!untilNoLongerPossibleToGraze && flag) || (untilNoLongerPossibleToGraze && !flag))
                {
                    return(new float?(num));
                }
                num += 0.45f;
            }
            return(null);
        }
        public static float ApproxDaysWorthOfFood(List <Pawn> pawns, List <Thing> potentiallyFood, bool assumeCanEatLocalPlants, IgnorePawnsInventoryMode ignoreInventory)
        {
            DaysWorthOfFoodCalculator.tmpThingCounts.Clear();
            DaysWorthOfFoodCalculator.tmpPawns.Clear();
            for (int i = 0; i < pawns.Count; i++)
            {
                Pawn pawn = pawns[i];
                if (pawn.RaceProps.EatsFood && (!assumeCanEatLocalPlants || !VirtualPlantsUtility.CanEverEatVirtualPlants(pawn)))
                {
                    DaysWorthOfFoodCalculator.tmpPawns.Add(pawn);
                }
            }
            for (int j = 0; j < potentiallyFood.Count; j++)
            {
                DaysWorthOfFoodCalculator.tmpThingCounts.Add(new ThingCount(potentiallyFood[j].def, potentiallyFood[j].stackCount));
            }
            float result = DaysWorthOfFoodCalculator.ApproxDaysWorthOfFood(DaysWorthOfFoodCalculator.tmpPawns, DaysWorthOfFoodCalculator.tmpThingCounts, assumeCanEatLocalPlants, ignoreInventory);

            DaysWorthOfFoodCalculator.tmpThingCounts.Clear();
            DaysWorthOfFoodCalculator.tmpPawns.Clear();
            return(result);
        }
        public static float ApproxDaysWorthOfFoodLeftAfterTransfer(List <TransferableOneWay> transferables, bool assumeCanEatLocalPlants, IgnorePawnsInventoryMode ignoreInventory)
        {
            DaysWorthOfFoodCalculator.tmpThingCounts.Clear();
            DaysWorthOfFoodCalculator.tmpPawns.Clear();
            for (int i = 0; i < transferables.Count; i++)
            {
                TransferableOneWay transferableOneWay = transferables[i];
                if (transferableOneWay.HasAnyThing)
                {
                    if (transferableOneWay.AnyThing is Pawn)
                    {
                        for (int num = transferableOneWay.things.Count - 1; num >= transferableOneWay.CountToTransfer; num--)
                        {
                            Pawn pawn = (Pawn)transferableOneWay.things[num];
                            if (pawn.RaceProps.EatsFood && (!assumeCanEatLocalPlants || !VirtualPlantsUtility.CanEverEatVirtualPlants(pawn)))
                            {
                                DaysWorthOfFoodCalculator.tmpPawns.Add(pawn);
                            }
                        }
                    }
                    else
                    {
                        DaysWorthOfFoodCalculator.tmpThingCounts.Add(new ThingCount(transferableOneWay.ThingDef, transferableOneWay.MaxCount - transferableOneWay.CountToTransfer));
                    }
                }
            }
            float result = DaysWorthOfFoodCalculator.ApproxDaysWorthOfFood(DaysWorthOfFoodCalculator.tmpPawns, DaysWorthOfFoodCalculator.tmpThingCounts, assumeCanEatLocalPlants, ignoreInventory);

            DaysWorthOfFoodCalculator.tmpThingCounts.Clear();
            DaysWorthOfFoodCalculator.tmpPawns.Clear();
            return(result);
        }
 public static bool CanEatVirtualPlantsNow(Pawn p)
 {
     return(VirtualPlantsUtility.CanEatVirtualPlants(p, GenTicks.TicksAbs));
 }
Beispiel #12
0
        public static void DrawCaravanInfo(CaravanInfo info, CaravanInfo?info2, int currentTile, int?ticksToArrive, float lastMassFlashTime, Rect rect, bool lerpMassColor = true, string extraDaysWorthOfFoodTipInfo = null, bool multiline = false)
        {
            tmpInfo.Clear();
            TaggedString taggedString  = info.massUsage.ToStringEnsureThreshold(info.massCapacity, 0) + " / " + info.massCapacity.ToString("F0") + " " + "kg".Translate();
            TaggedString taggedString2 = info2.HasValue ? (info2.Value.massUsage.ToStringEnsureThreshold(info2.Value.massCapacity, 0) + " / " + info2.Value.massCapacity.ToString("F0") + " " + "kg".Translate()) : ((TaggedString)null);

            tmpInfo.Add(new TransferableUIUtility.ExtraInfo("Mass".Translate(), taggedString, GetMassColor(info.massUsage, info.massCapacity, lerpMassColor), GetMassTip(info.massUsage, info.massCapacity, info.massCapacityExplanation, info2.HasValue ? new float?(info2.Value.massUsage) : null, info2.HasValue ? new float?(info2.Value.massCapacity) : null, info2.HasValue ? info2.Value.massCapacityExplanation : null), taggedString2, info2.HasValue ? GetMassColor(info2.Value.massUsage, info2.Value.massCapacity, lerpMassColor) : Color.white, lastMassFlashTime));
            if (info.extraMassUsage != -1f)
            {
                TaggedString taggedString3 = info.extraMassUsage.ToStringEnsureThreshold(info.extraMassCapacity, 0) + " / " + info.extraMassCapacity.ToString("F0") + " " + "kg".Translate();
                TaggedString taggedString4 = info2.HasValue ? (info2.Value.extraMassUsage.ToStringEnsureThreshold(info2.Value.extraMassCapacity, 0) + " / " + info2.Value.extraMassCapacity.ToString("F0") + " " + "kg".Translate()) : ((TaggedString)null);
                tmpInfo.Add(new TransferableUIUtility.ExtraInfo("CaravanMass".Translate(), taggedString3, GetMassColor(info.extraMassUsage, info.extraMassCapacity, lerpMassColor: true), GetMassTip(info.extraMassUsage, info.extraMassCapacity, info.extraMassCapacityExplanation, info2.HasValue ? new float?(info2.Value.extraMassUsage) : null, info2.HasValue ? new float?(info2.Value.extraMassCapacity) : null, info2.HasValue ? info2.Value.extraMassCapacityExplanation : null), taggedString4, info2.HasValue ? GetMassColor(info2.Value.extraMassUsage, info2.Value.extraMassCapacity, lerpMassColor: true) : Color.white));
            }
            string text = "CaravanMovementSpeedTip".Translate();

            if (!info.tilesPerDayExplanation.NullOrEmpty())
            {
                text = text + "\n\n" + info.tilesPerDayExplanation;
            }
            if (info2.HasValue && !info2.Value.tilesPerDayExplanation.NullOrEmpty())
            {
                text = text + "\n\n-----\n\n" + info2.Value.tilesPerDayExplanation;
            }
            tmpInfo.Add(new TransferableUIUtility.ExtraInfo("CaravanMovementSpeed".Translate(), info.tilesPerDay.ToString("0.#") + " " + "TilesPerDay".Translate(), GenUI.LerpColor(TilesPerDayColor, info.tilesPerDay), text, info2.HasValue ? (info2.Value.tilesPerDay.ToString("0.#") + " " + "TilesPerDay".Translate()) : ((TaggedString)null), info2.HasValue ? GenUI.LerpColor(TilesPerDayColor, info2.Value.tilesPerDay) : Color.white));
            tmpInfo.Add(new TransferableUIUtility.ExtraInfo("DaysWorthOfFood".Translate(), GetDaysWorthOfFoodLabel(info.daysWorthOfFood, multiline), GetDaysWorthOfFoodColor(info.daysWorthOfFood, ticksToArrive), "DaysWorthOfFoodTooltip".Translate() + extraDaysWorthOfFoodTipInfo + "\n\n" + VirtualPlantsUtility.GetVirtualPlantsStatusExplanationAt(currentTile, Find.TickManager.TicksAbs), info2.HasValue ? GetDaysWorthOfFoodLabel(info2.Value.daysWorthOfFood, multiline) : null, info2.HasValue ? GetDaysWorthOfFoodColor(info2.Value.daysWorthOfFood, ticksToArrive) : Color.white));
            string       text2         = info.foragedFoodPerDay.Second.ToString("0.#");
            string       text3         = info2.HasValue ? info2.Value.foragedFoodPerDay.Second.ToString("0.#") : null;
            TaggedString taggedString5 = "ForagedFoodPerDayTip".Translate();

            taggedString5 += "\n\n" + info.foragedFoodPerDayExplanation;
            if (info2.HasValue)
            {
                taggedString5 += "\n\n-----\n\n" + info2.Value.foragedFoodPerDayExplanation;
            }
            if (info.foragedFoodPerDay.Second > 0f || (info2.HasValue && info2.Value.foragedFoodPerDay.Second > 0f))
            {
                string text4 = multiline ? "\n" : " ";
                if (!info2.HasValue)
                {
                    text2 = text2 + text4 + "(" + info.foragedFoodPerDay.First.label + ")";
                }
                else
                {
                    text3 = text3 + text4 + "(" + info2.Value.foragedFoodPerDay.First.label.Truncate(50f) + ")";
                }
            }
            tmpInfo.Add(new TransferableUIUtility.ExtraInfo("ForagedFoodPerDay".Translate(), text2, Color.white, taggedString5, text3, Color.white));
            string text5 = "CaravanVisibilityTip".Translate();

            if (!info.visibilityExplanation.NullOrEmpty())
            {
                text5 = text5 + "\n\n" + info.visibilityExplanation;
            }
            if (info2.HasValue && !info2.Value.visibilityExplanation.NullOrEmpty())
            {
                text5 = text5 + "\n\n-----\n\n" + info2.Value.visibilityExplanation;
            }
            tmpInfo.Add(new TransferableUIUtility.ExtraInfo("Visibility".Translate(), info.visibility.ToStringPercent(), GenUI.LerpColor(VisibilityColor, info.visibility), text5, info2.HasValue ? info2.Value.visibility.ToStringPercent() : null, info2.HasValue ? GenUI.LerpColor(VisibilityColor, info2.Value.visibility) : Color.white));
            TransferableUIUtility.DrawExtraInfo(tmpInfo, rect);
        }
 public static float ApproxDaysWorthOfFood(Caravan caravan)
 {
     return(DaysWorthOfFoodCalculator.ApproxDaysWorthOfFood(caravan.PawnsListForReading, (List <ThingCount>)null, VirtualPlantsUtility.EnvironmentAllowsEatingVirtualPlantsNowAt(caravan.Tile), IgnorePawnsInventoryMode.DontIgnore));
 }
Beispiel #14
0
        public static void DrawCaravanInfo(CaravanInfo info, CaravanInfo?info2, int currentTile, int?ticksToArrive, float lastMassFlashTime, Rect rect, bool lerpMassColor = true, string extraDaysWorthOfFoodTipInfo = null, bool multiline = false)
        {
            tmpInfo.Clear();
            string text = info.massUsage.ToStringEnsureThreshold(info.massCapacity, 0) + " / " + info.massCapacity.ToString("F0") + " " + "kg".Translate();
            object obj2;

            if (info2.HasValue)
            {
                string[]    obj       = new string[5];
                CaravanInfo value     = info2.Value;
                float       massUsage = value.massUsage;
                CaravanInfo value2    = info2.Value;
                obj[0] = massUsage.ToStringEnsureThreshold(value2.massCapacity, 0);
                obj[1] = " / ";
                CaravanInfo value3 = info2.Value;
                obj[2] = value3.massCapacity.ToString("F0");
                obj[3] = " ";
                obj[4] = "kg".Translate();
                obj2   = string.Concat(obj);
            }
            else
            {
                obj2 = null;
            }
            string text2 = (string)obj2;
            List <TransferableUIUtility.ExtraInfo> list = tmpInfo;
            string key                     = "Mass".Translate();
            string value4                  = text;
            Color  massColor               = GetMassColor(info.massUsage, info.massCapacity, lerpMassColor);
            float  massUsage2              = info.massUsage;
            float  massCapacity            = info.massCapacity;
            string massCapacityExplanation = info.massCapacityExplanation;
            float? massUsage3;

            if (info2.HasValue)
            {
                CaravanInfo value5 = info2.Value;
                massUsage3 = value5.massUsage;
            }
            else
            {
                massUsage3 = null;
            }
            float?massCapacity2;

            if (info2.HasValue)
            {
                CaravanInfo value6 = info2.Value;
                massCapacity2 = value6.massCapacity;
            }
            else
            {
                massCapacity2 = null;
            }
            object massCapacity2Explanation;

            if (info2.HasValue)
            {
                CaravanInfo value7 = info2.Value;
                massCapacity2Explanation = value7.massCapacityExplanation;
            }
            else
            {
                massCapacity2Explanation = null;
            }
            string massTip     = GetMassTip(massUsage2, massCapacity, massCapacityExplanation, massUsage3, massCapacity2, (string)massCapacity2Explanation);
            string secondValue = text2;
            Color  secondColor;

            if (info2.HasValue)
            {
                CaravanInfo value8     = info2.Value;
                float       massUsage4 = value8.massUsage;
                CaravanInfo value9     = info2.Value;
                secondColor = GetMassColor(massUsage4, value9.massCapacity, lerpMassColor);
            }
            else
            {
                secondColor = Color.white;
            }
            list.Add(new TransferableUIUtility.ExtraInfo(key, value4, massColor, massTip, secondValue, secondColor, lastMassFlashTime));
            if (info.extraMassUsage != -1f)
            {
                string text3 = info.extraMassUsage.ToStringEnsureThreshold(info.extraMassCapacity, 0) + " / " + info.extraMassCapacity.ToString("F0") + " " + "kg".Translate();
                object obj4;
                if (info2.HasValue)
                {
                    string[]    obj3           = new string[5];
                    CaravanInfo value10        = info2.Value;
                    float       extraMassUsage = value10.extraMassUsage;
                    CaravanInfo value11        = info2.Value;
                    obj3[0] = extraMassUsage.ToStringEnsureThreshold(value11.extraMassCapacity, 0);
                    obj3[1] = " / ";
                    CaravanInfo value12 = info2.Value;
                    obj3[2] = value12.extraMassCapacity.ToString("F0");
                    obj3[3] = " ";
                    obj3[4] = "kg".Translate();
                    obj4    = string.Concat(obj3);
                }
                else
                {
                    obj4 = null;
                }
                string text4 = (string)obj4;
                List <TransferableUIUtility.ExtraInfo> list2 = tmpInfo;
                string key2                         = "CaravanMass".Translate();
                string value13                      = text3;
                Color  massColor2                   = GetMassColor(info.extraMassUsage, info.extraMassCapacity, lerpMassColor: true);
                float  extraMassUsage2              = info.extraMassUsage;
                float  extraMassCapacity            = info.extraMassCapacity;
                string extraMassCapacityExplanation = info.extraMassCapacityExplanation;
                float? massUsage5;
                if (info2.HasValue)
                {
                    CaravanInfo value14 = info2.Value;
                    massUsage5 = value14.extraMassUsage;
                }
                else
                {
                    massUsage5 = null;
                }
                float?massCapacity3;
                if (info2.HasValue)
                {
                    CaravanInfo value15 = info2.Value;
                    massCapacity3 = value15.extraMassCapacity;
                }
                else
                {
                    massCapacity3 = null;
                }
                object massCapacity2Explanation2;
                if (info2.HasValue)
                {
                    CaravanInfo value16 = info2.Value;
                    massCapacity2Explanation2 = value16.extraMassCapacityExplanation;
                }
                else
                {
                    massCapacity2Explanation2 = null;
                }
                string massTip2     = GetMassTip(extraMassUsage2, extraMassCapacity, extraMassCapacityExplanation, massUsage5, massCapacity3, (string)massCapacity2Explanation2);
                string secondValue2 = text4;
                Color  secondColor2;
                if (info2.HasValue)
                {
                    CaravanInfo value17         = info2.Value;
                    float       extraMassUsage3 = value17.extraMassUsage;
                    CaravanInfo value18         = info2.Value;
                    secondColor2 = GetMassColor(extraMassUsage3, value18.extraMassCapacity, lerpMassColor: true);
                }
                else
                {
                    secondColor2 = Color.white;
                }
                list2.Add(new TransferableUIUtility.ExtraInfo(key2, value13, massColor2, massTip2, secondValue2, secondColor2));
            }
            string text5 = "CaravanMovementSpeedTip".Translate();

            if (!info.tilesPerDayExplanation.NullOrEmpty())
            {
                text5 = text5 + "\n\n" + info.tilesPerDayExplanation;
            }
            if (info2.HasValue)
            {
                CaravanInfo value19 = info2.Value;
                if (!value19.tilesPerDayExplanation.NullOrEmpty())
                {
                    string      str     = text5;
                    CaravanInfo value20 = info2.Value;
                    text5 = str + "\n\n-----\n\n" + value20.tilesPerDayExplanation;
                }
            }
            List <TransferableUIUtility.ExtraInfo> list3 = tmpInfo;
            string key3    = "CaravanMovementSpeed".Translate();
            string value21 = info.tilesPerDay.ToString("0.#") + " " + "TilesPerDay".Translate();
            Color  color   = GenUI.LerpColor(TilesPerDayColor, info.tilesPerDay);
            string tip     = text5;
            object secondValue3;

            if (info2.HasValue)
            {
                CaravanInfo value22 = info2.Value;
                secondValue3 = value22.tilesPerDay.ToString("0.#") + " " + "TilesPerDay".Translate();
            }
            else
            {
                secondValue3 = null;
            }
            Color secondColor3;

            if (info2.HasValue)
            {
                List <Pair <float, Color> > tilesPerDayColor = TilesPerDayColor;
                CaravanInfo value23 = info2.Value;
                secondColor3 = GenUI.LerpColor(tilesPerDayColor, value23.tilesPerDay);
            }
            else
            {
                secondColor3 = Color.white;
            }
            list3.Add(new TransferableUIUtility.ExtraInfo(key3, value21, color, tip, (string)secondValue3, secondColor3));
            List <TransferableUIUtility.ExtraInfo> list4 = tmpInfo;
            string key4 = "DaysWorthOfFood".Translate();
            string daysWorthOfFoodLabel = GetDaysWorthOfFoodLabel(info.daysWorthOfFood, multiline);
            Color  daysWorthOfFoodColor = GetDaysWorthOfFoodColor(info.daysWorthOfFood, ticksToArrive);
            string tip2 = "DaysWorthOfFoodTooltip".Translate() + extraDaysWorthOfFoodTipInfo + "\n\n" + VirtualPlantsUtility.GetVirtualPlantsStatusExplanationAt(currentTile, Find.TickManager.TicksAbs);
            object secondValue4;

            if (info2.HasValue)
            {
                CaravanInfo value24 = info2.Value;
                secondValue4 = GetDaysWorthOfFoodLabel(value24.daysWorthOfFood, multiline);
            }
            else
            {
                secondValue4 = null;
            }
            Color secondColor4;

            if (info2.HasValue)
            {
                CaravanInfo value25 = info2.Value;
                secondColor4 = GetDaysWorthOfFoodColor(value25.daysWorthOfFood, ticksToArrive);
            }
            else
            {
                secondColor4 = Color.white;
            }
            list4.Add(new TransferableUIUtility.ExtraInfo(key4, daysWorthOfFoodLabel, daysWorthOfFoodColor, tip2, (string)secondValue4, secondColor4));
            string text6 = info.foragedFoodPerDay.Second.ToString("0.#");
            object obj5;

            if (info2.HasValue)
            {
                CaravanInfo value26 = info2.Value;
                obj5 = value26.foragedFoodPerDay.Second.ToString("0.#");
            }
            else
            {
                obj5 = null;
            }
            string text7 = (string)obj5;
            string str2  = "ForagedFoodPerDayTip".Translate();

            str2 = str2 + "\n\n" + info.foragedFoodPerDayExplanation;
            if (info2.HasValue)
            {
                string      str3    = str2;
                CaravanInfo value27 = info2.Value;
                str2 = str3 + "\n\n-----\n\n" + value27.foragedFoodPerDayExplanation;
            }
            if (info.foragedFoodPerDay.Second > 0f)
            {
                goto IL_06ad;
            }
            if (info2.HasValue)
            {
                CaravanInfo value28 = info2.Value;
                if (value28.foragedFoodPerDay.Second > 0f)
                {
                    goto IL_06ad;
                }
            }
            goto IL_076b;
IL_06ad:
            string text8 = (!multiline) ? " " : "\n";

            if (!info2.HasValue)
            {
                string text9 = text6;
                text6 = text9 + text8 + "(" + info.foragedFoodPerDay.First.label + ")";
            }
            else
            {
                string   text9 = text7;
                string[] obj6  = new string[5]
                {
                    text9,
                    text8,
                    "(",
                    null,
                    null
                };
                CaravanInfo value29 = info2.Value;
                obj6[3] = value29.foragedFoodPerDay.First.label.Truncate(50f);
                obj6[4] = ")";
                text7   = string.Concat(obj6);
            }
            goto IL_076b;
IL_076b:
            tmpInfo.Add(new TransferableUIUtility.ExtraInfo("ForagedFoodPerDay".Translate(), text6, Color.white, str2, text7, Color.white));
            string text10 = "CaravanVisibilityTip".Translate();

            if (!info.visibilityExplanation.NullOrEmpty())
            {
                text10 = text10 + "\n\n" + info.visibilityExplanation;
            }
            if (info2.HasValue)
            {
                CaravanInfo value30 = info2.Value;
                if (!value30.visibilityExplanation.NullOrEmpty())
                {
                    string      str4    = text10;
                    CaravanInfo value31 = info2.Value;
                    text10 = str4 + "\n\n-----\n\n" + value31.visibilityExplanation;
                }
            }
            List <TransferableUIUtility.ExtraInfo> list5 = tmpInfo;
            string key5    = "Visibility".Translate();
            string value32 = info.visibility.ToStringPercent();
            Color  color2  = GenUI.LerpColor(VisibilityColor, info.visibility);
            string tip3    = text10;
            object secondValue5;

            if (info2.HasValue)
            {
                CaravanInfo value33 = info2.Value;
                secondValue5 = value33.visibility.ToStringPercent();
            }
            else
            {
                secondValue5 = null;
            }
            Color secondColor5;

            if (info2.HasValue)
            {
                List <Pair <float, Color> > visibilityColor = VisibilityColor;
                CaravanInfo value34 = info2.Value;
                secondColor5 = GenUI.LerpColor(visibilityColor, value34.visibility);
            }
            else
            {
                secondColor5 = Color.white;
            }
            list5.Add(new TransferableUIUtility.ExtraInfo(key5, value32, color2, tip3, (string)secondValue5, secondColor5));
            TransferableUIUtility.DrawExtraInfo(tmpInfo, rect);
        }
Beispiel #15
0
        protected override void FillTab()
        {
            Rect outRect = new Rect(0f, 0f, WITab_Terrain.WinSize.x, WITab_Terrain.WinSize.y).ContractedBy(10f);
            Rect rect    = new Rect(0f, 0f, outRect.width - 16f, Mathf.Max(this.lastDrawnHeight, outRect.height));

            Widgets.BeginScrollView(outRect, ref this.scrollPosition, rect, true);
            Rect rect2 = rect;
            Rect rect3 = rect2;

            Text.Font = GameFont.Medium;
            Widgets.Label(rect3, base.SelTile.biome.LabelCap);
            Rect rect4 = rect2;

            rect4.yMin  += 35f;
            rect4.height = 99999f;
            Text.Font    = GameFont.Small;
            Listing_Standard listing_Standard = new Listing_Standard();

            listing_Standard.verticalSpacing = 0f;
            listing_Standard.Begin(rect4);
            Tile selTile   = base.SelTile;
            int  selTileID = base.SelTileID;

            listing_Standard.Label(selTile.biome.description, -1f, null);
            listing_Standard.Gap(8f);
            listing_Standard.GapLine(12f);
            if (!selTile.biome.implemented)
            {
                listing_Standard.Label(selTile.biome.LabelCap + " " + "BiomeNotImplemented".Translate(), -1f, null);
            }
            listing_Standard.LabelDouble("Terrain".Translate(), selTile.hilliness.GetLabelCap(), null);
            if (selTile.Roads != null)
            {
                listing_Standard.LabelDouble("Road".Translate(), (from roadlink in selTile.Roads
                                                                  select roadlink.road.label).Distinct <string>().ToCommaList(true).CapitalizeFirst(), null);
            }
            if (selTile.Rivers != null)
            {
                listing_Standard.LabelDouble("River".Translate(), selTile.Rivers.MaxBy((Tile.RiverLink riverlink) => riverlink.river.degradeThreshold).river.LabelCap, null);
            }
            if (!Find.World.Impassable(selTileID))
            {
                StringBuilder stringBuilder   = new StringBuilder();
                int           tile            = selTileID;
                bool          perceivedStatic = false;
                StringBuilder explanation     = stringBuilder;
                string        rightLabel      = (WorldPathGrid.CalculatedMovementDifficultyAt(tile, perceivedStatic, null, explanation) * Find.WorldGrid.GetRoadMovementDifficultyMultiplier(selTileID, -1, stringBuilder)).ToString("0.#");
                if (WorldPathGrid.WillWinterEverAffectMovementDifficulty(selTileID) && WorldPathGrid.GetCurrentWinterMovementDifficultyOffset(selTileID, null, null) < 2f)
                {
                    stringBuilder.AppendLine();
                    stringBuilder.AppendLine();
                    stringBuilder.Append(" (");
                    stringBuilder.Append("MovementDifficultyOffsetInWinter".Translate(new object[]
                    {
                        "+" + 2f.ToString("0.#")
                    }));
                    stringBuilder.Append(")");
                }
                listing_Standard.LabelDouble("MovementDifficulty".Translate(), rightLabel, stringBuilder.ToString());
            }
            if (selTile.biome.canBuildBase)
            {
                listing_Standard.LabelDouble("StoneTypesHere".Translate(), (from rt in Find.World.NaturalRockTypesIn(selTileID)
                                                                            select rt.label).ToCommaList(true).CapitalizeFirst(), null);
            }
            listing_Standard.LabelDouble("Elevation".Translate(), selTile.elevation.ToString("F0") + "m", null);
            listing_Standard.GapLine(12f);
            listing_Standard.LabelDouble("AvgTemp".Translate(), GenTemperature.GetAverageTemperatureLabel(selTileID), null);
            listing_Standard.LabelDouble("OutdoorGrowingPeriod".Translate(), Zone_Growing.GrowingQuadrumsDescription(selTileID), null);
            listing_Standard.LabelDouble("Rainfall".Translate(), selTile.rainfall.ToString("F0") + "mm", null);
            if (selTile.biome.foragedFood != null && selTile.biome.forageability > 0f)
            {
                listing_Standard.LabelDouble("Forageability".Translate(), selTile.biome.forageability.ToStringPercent() + " (" + selTile.biome.foragedFood.label + ")", null);
            }
            else
            {
                listing_Standard.LabelDouble("Forageability".Translate(), "0%", null);
            }
            listing_Standard.LabelDouble("AnimalsCanGrazeNow".Translate(), (!VirtualPlantsUtility.EnvironmentAllowsEatingVirtualPlantsNowAt(selTileID)) ? "No".Translate() : "Yes".Translate(), null);
            listing_Standard.GapLine(12f);
            listing_Standard.LabelDouble("AverageDiseaseFrequency".Translate(), string.Format("{0} {1}", (60f / selTile.biome.diseaseMtbDays).ToString("F1"), "PerYear".Translate()), null);
            listing_Standard.LabelDouble("TimeZone".Translate(), GenDate.TimeZoneAt(Find.WorldGrid.LongLatOf(selTileID).x).ToStringWithSign(), null);
            StringBuilder stringBuilder2 = new StringBuilder();
            Rot4          rot            = Find.World.CoastDirectionAt(selTileID);

            if (rot.IsValid)
            {
                stringBuilder2.AppendWithComma(("HasCoast" + rot.ToString()).Translate());
            }
            if (Find.World.HasCaves(selTileID))
            {
                stringBuilder2.AppendWithComma("HasCaves".Translate());
            }
            if (stringBuilder2.Length > 0)
            {
                listing_Standard.LabelDouble("SpecialFeatures".Translate(), stringBuilder2.ToString().CapitalizeFirst(), null);
            }
            if (Prefs.DevMode)
            {
                listing_Standard.LabelDouble("Debug world tile ID", selTileID.ToString(), null);
            }
            this.lastDrawnHeight = rect4.y + listing_Standard.CurHeight;
            listing_Standard.End();
            Widgets.EndScrollView();
        }
        private static float ApproxDaysWorthOfFood(List <Pawn> pawns, List <ThingDefCount> extraFood, int tile, IgnorePawnsInventoryMode ignoreInventory, Faction faction, WorldPath path = null, float nextTileCostLeft = 0f, int caravanTicksPerMove = 3500, bool assumeCaravanMoving = true)
        {
            float result;

            if (!DaysWorthOfFoodCalculator.AnyFoodEatingPawn(pawns))
            {
                result = 600f;
            }
            else
            {
                if (!assumeCaravanMoving)
                {
                    path = null;
                }
                DaysWorthOfFoodCalculator.tmpFood.Clear();
                if (extraFood != null)
                {
                    int i     = 0;
                    int count = extraFood.Count;
                    while (i < count)
                    {
                        ThingDefCount item = extraFood[i];
                        if (item.ThingDef.IsNutritionGivingIngestible && item.Count > 0)
                        {
                            DaysWorthOfFoodCalculator.tmpFood.Add(item);
                        }
                        i++;
                    }
                }
                int j      = 0;
                int count2 = pawns.Count;
                while (j < count2)
                {
                    Pawn pawn = pawns[j];
                    if (!InventoryCalculatorsUtility.ShouldIgnoreInventoryOf(pawn, ignoreInventory))
                    {
                        ThingOwner <Thing> innerContainer = pawn.inventory.innerContainer;
                        int k      = 0;
                        int count3 = innerContainer.Count;
                        while (k < count3)
                        {
                            Thing thing = innerContainer[k];
                            if (thing.def.IsNutritionGivingIngestible)
                            {
                                DaysWorthOfFoodCalculator.tmpFood.Add(new ThingDefCount(thing.def, thing.stackCount));
                            }
                            k++;
                        }
                    }
                    j++;
                }
                DaysWorthOfFoodCalculator.tmpFood2.Clear();
                DaysWorthOfFoodCalculator.tmpFood2.AddRange(DaysWorthOfFoodCalculator.tmpFood);
                DaysWorthOfFoodCalculator.tmpFood.Clear();
                int l      = 0;
                int count4 = DaysWorthOfFoodCalculator.tmpFood2.Count;
                while (l < count4)
                {
                    ThingDefCount item2  = DaysWorthOfFoodCalculator.tmpFood2[l];
                    bool          flag   = false;
                    int           m      = 0;
                    int           count5 = DaysWorthOfFoodCalculator.tmpFood.Count;
                    while (m < count5)
                    {
                        ThingDefCount thingDefCount = DaysWorthOfFoodCalculator.tmpFood[m];
                        if (thingDefCount.ThingDef == item2.ThingDef)
                        {
                            DaysWorthOfFoodCalculator.tmpFood[m] = thingDefCount.WithCount(thingDefCount.Count + item2.Count);
                            flag = true;
                            break;
                        }
                        m++;
                    }
                    if (!flag)
                    {
                        DaysWorthOfFoodCalculator.tmpFood.Add(item2);
                    }
                    l++;
                }
                DaysWorthOfFoodCalculator.tmpDaysWorthOfFoodForPawn.Clear();
                int n      = 0;
                int count6 = pawns.Count;
                while (n < count6)
                {
                    DaysWorthOfFoodCalculator.tmpDaysWorthOfFoodForPawn.Add(0f);
                    n++;
                }
                int ticksAbs = Find.TickManager.TicksAbs;
                DaysWorthOfFoodCalculator.tmpTicksToArrive.Clear();
                if (path != null && path.Found)
                {
                    CaravanArrivalTimeEstimator.EstimatedTicksToArriveToEvery(tile, path.LastNode, path, nextTileCostLeft, caravanTicksPerMove, ticksAbs, DaysWorthOfFoodCalculator.tmpTicksToArrive);
                }
                DaysWorthOfFoodCalculator.cachedNutritionBetweenHungryAndFed.Clear();
                DaysWorthOfFoodCalculator.cachedTicksUntilHungryWhenFed.Clear();
                DaysWorthOfFoodCalculator.cachedMaxFoodLevel.Clear();
                int num    = 0;
                int count7 = pawns.Count;
                while (num < count7)
                {
                    Pawn      pawn2 = pawns[num];
                    Need_Food food  = pawn2.needs.food;
                    DaysWorthOfFoodCalculator.cachedNutritionBetweenHungryAndFed.Add(food.NutritionBetweenHungryAndFed);
                    DaysWorthOfFoodCalculator.cachedTicksUntilHungryWhenFed.Add(food.TicksUntilHungryWhenFed);
                    DaysWorthOfFoodCalculator.cachedMaxFoodLevel.Add(food.MaxLevel);
                    num++;
                }
                float     num2      = 0f;
                float     num3      = 0f;
                float     num4      = 0f;
                bool      flag2     = false;
                WorldGrid worldGrid = Find.WorldGrid;
                bool      flag3;
                do
                {
                    flag3 = false;
                    int   num5            = ticksAbs + (int)(num3 * 60000f);
                    int   num6            = (path == null) ? tile : CaravanArrivalTimeEstimator.TileIllBeInAt(num5, DaysWorthOfFoodCalculator.tmpTicksToArrive, ticksAbs);
                    bool  flag4           = CaravanRestUtility.WouldBeRestingAt(num6, (long)num5);
                    float progressPerTick = ForagedFoodPerDayCalculator.GetProgressPerTick(assumeCaravanMoving && !flag4, flag4, null);
                    float num7            = 1f / progressPerTick;
                    bool  flag5           = VirtualPlantsUtility.EnvironmentAllowsEatingVirtualPlantsAt(num6, num5);
                    float num8            = num3 - num2;
                    if (num8 > 0f)
                    {
                        num4 += num8 * 60000f;
                        if (num4 >= num7)
                        {
                            BiomeDef biome       = worldGrid[num6].biome;
                            int      num9        = Mathf.RoundToInt(ForagedFoodPerDayCalculator.GetForagedFoodCountPerInterval(pawns, biome, faction, null));
                            ThingDef foragedFood = biome.foragedFood;
                            while (num4 >= num7)
                            {
                                num4 -= num7;
                                if (num9 > 0)
                                {
                                    bool flag6 = false;
                                    for (int num10 = DaysWorthOfFoodCalculator.tmpFood.Count - 1; num10 >= 0; num10--)
                                    {
                                        ThingDefCount thingDefCount2 = DaysWorthOfFoodCalculator.tmpFood[num10];
                                        if (thingDefCount2.ThingDef == foragedFood)
                                        {
                                            DaysWorthOfFoodCalculator.tmpFood[num10] = thingDefCount2.WithCount(thingDefCount2.Count + num9);
                                            flag6 = true;
                                            break;
                                        }
                                    }
                                    if (!flag6)
                                    {
                                        DaysWorthOfFoodCalculator.tmpFood.Add(new ThingDefCount(foragedFood, num9));
                                    }
                                }
                            }
                        }
                    }
                    num2 = num3;
                    int num11  = 0;
                    int count8 = pawns.Count;
                    while (num11 < count8)
                    {
                        Pawn pawn3 = pawns[num11];
                        if (pawn3.RaceProps.EatsFood)
                        {
                            if (flag5 && VirtualPlantsUtility.CanEverEatVirtualPlants(pawn3))
                            {
                                if (DaysWorthOfFoodCalculator.tmpDaysWorthOfFoodForPawn[num11] < num3)
                                {
                                    DaysWorthOfFoodCalculator.tmpDaysWorthOfFoodForPawn[num11] = num3;
                                }
                                else
                                {
                                    List <float> list;
                                    int          index;
                                    (list = DaysWorthOfFoodCalculator.tmpDaysWorthOfFoodForPawn)[index = num11] = list[index] + 0.45f;
                                }
                                flag3 = true;
                            }
                            else
                            {
                                float num12 = DaysWorthOfFoodCalculator.cachedNutritionBetweenHungryAndFed[num11];
                                int   num13 = DaysWorthOfFoodCalculator.cachedTicksUntilHungryWhenFed[num11];
                                do
                                {
                                    int num14 = DaysWorthOfFoodCalculator.BestEverEdibleFoodIndexFor(pawn3, DaysWorthOfFoodCalculator.tmpFood);
                                    if (num14 < 0)
                                    {
                                        goto Block_27;
                                    }
                                    ThingDefCount thingDefCount3 = DaysWorthOfFoodCalculator.tmpFood[num14];
                                    float         num15          = Mathf.Min(thingDefCount3.ThingDef.ingestible.CachedNutrition, num12);
                                    float         num16          = num15 / num12 * (float)num13 / 60000f;
                                    int           num17          = Mathf.Min(Mathf.CeilToInt(Mathf.Min(0.2f, DaysWorthOfFoodCalculator.cachedMaxFoodLevel[num11]) / num15), thingDefCount3.Count);
                                    List <float>  list;
                                    int           index2;
                                    (list = DaysWorthOfFoodCalculator.tmpDaysWorthOfFoodForPawn)[index2 = num11] = list[index2] + num16 * (float)num17;
                                    DaysWorthOfFoodCalculator.tmpFood[num14] = thingDefCount3.WithCount(thingDefCount3.Count - num17);
                                    flag3 = true;
                                }while (DaysWorthOfFoodCalculator.tmpDaysWorthOfFoodForPawn[num11] < num3);
                                goto IL_633;
Block_27:
                                if (DaysWorthOfFoodCalculator.tmpDaysWorthOfFoodForPawn[num11] < num3)
                                {
                                    flag2 = true;
                                }
                            }
IL_633:
                            if (flag2)
                            {
                                break;
                            }
                            num3 = Mathf.Max(num3, DaysWorthOfFoodCalculator.tmpDaysWorthOfFoodForPawn[num11]);
                        }
                        num11++;
                    }
                }while (flag3 && !flag2 && num3 <= 601f);
                float num18  = 600f;
                int   num19  = 0;
                int   count9 = pawns.Count;
                while (num19 < count9)
                {
                    if (pawns[num19].RaceProps.EatsFood)
                    {
                        num18 = Mathf.Min(num18, DaysWorthOfFoodCalculator.tmpDaysWorthOfFoodForPawn[num19]);
                    }
                    num19++;
                }
                result = num18;
            }
            return(result);
        }
 public static bool EnvironmentAllowsEatingVirtualPlantsNowAt(int tile)
 {
     return(VirtualPlantsUtility.EnvironmentAllowsEatingVirtualPlantsAt(tile, GenTicks.TicksAbs));
 }
Beispiel #18
0
        private static float ApproxDaysWorthOfFood(List <Pawn> pawns, List <ThingDefCount> extraFood, int tile, IgnorePawnsInventoryMode ignoreInventory, Faction faction, WorldPath path = null, float nextTileCostLeft = 0f, int caravanTicksPerMove = 3300, bool assumeCaravanMoving = true)
        {
            if (!AnyFoodEatingPawn(pawns))
            {
                return(600f);
            }
            if (!assumeCaravanMoving)
            {
                path = null;
            }
            tmpFood.Clear();
            if (extraFood != null)
            {
                int i = 0;
                for (int count = extraFood.Count; i < count; i++)
                {
                    ThingDefCount item = extraFood[i];
                    if (item.ThingDef.IsNutritionGivingIngestible && item.Count > 0)
                    {
                        tmpFood.Add(item);
                    }
                }
            }
            int j = 0;

            for (int count2 = pawns.Count; j < count2; j++)
            {
                Pawn pawn = pawns[j];
                if (InventoryCalculatorsUtility.ShouldIgnoreInventoryOf(pawn, ignoreInventory))
                {
                    continue;
                }
                ThingOwner <Thing> innerContainer = pawn.inventory.innerContainer;
                int k = 0;
                for (int count3 = innerContainer.Count; k < count3; k++)
                {
                    Thing thing = innerContainer[k];
                    if (thing.def.IsNutritionGivingIngestible)
                    {
                        tmpFood.Add(new ThingDefCount(thing.def, thing.stackCount));
                    }
                }
            }
            tmpFood2.Clear();
            tmpFood2.AddRange(tmpFood);
            tmpFood.Clear();
            int l = 0;

            for (int count4 = tmpFood2.Count; l < count4; l++)
            {
                ThingDefCount item2 = tmpFood2[l];
                bool          flag  = false;
                int           m     = 0;
                for (int count5 = tmpFood.Count; m < count5; m++)
                {
                    ThingDefCount thingDefCount = tmpFood[m];
                    if (thingDefCount.ThingDef == item2.ThingDef)
                    {
                        tmpFood[m] = thingDefCount.WithCount(thingDefCount.Count + item2.Count);
                        flag       = true;
                        break;
                    }
                }
                if (!flag)
                {
                    tmpFood.Add(item2);
                }
            }
            tmpDaysWorthOfFoodForPawn.Clear();
            int n = 0;

            for (int count6 = pawns.Count; n < count6; n++)
            {
                tmpDaysWorthOfFoodForPawn.Add(0f);
            }
            int ticksAbs = Find.TickManager.TicksAbs;

            tmpTicksToArrive.Clear();
            if (path != null && path.Found)
            {
                CaravanArrivalTimeEstimator.EstimatedTicksToArriveToEvery(tile, path.LastNode, path, nextTileCostLeft, caravanTicksPerMove, ticksAbs, tmpTicksToArrive);
            }
            cachedNutritionBetweenHungryAndFed.Clear();
            cachedTicksUntilHungryWhenFed.Clear();
            cachedMaxFoodLevel.Clear();
            int num = 0;

            for (int count7 = pawns.Count; num < count7; num++)
            {
                Pawn pawn2 = pawns[num];
                if (pawn2.RaceProps.EatsFood)
                {
                    Need_Food food = pawn2.needs.food;
                    cachedNutritionBetweenHungryAndFed.Add(food.NutritionBetweenHungryAndFed);
                    cachedTicksUntilHungryWhenFed.Add(food.TicksUntilHungryWhenFedIgnoringMalnutrition);
                    cachedMaxFoodLevel.Add(food.MaxLevel);
                }
                else
                {
                    cachedNutritionBetweenHungryAndFed.Add(0f);
                    cachedTicksUntilHungryWhenFed.Add(0);
                    cachedMaxFoodLevel.Add(0f);
                }
            }
            float     num2      = 0f;
            float     num3      = 0f;
            float     num4      = 0f;
            bool      flag2     = false;
            WorldGrid worldGrid = Find.WorldGrid;
            bool      flag3;

            do
            {
                flag3 = false;
                int   num5            = ticksAbs + (int)(num3 * 60000f);
                int   num6            = ((path != null) ? CaravanArrivalTimeEstimator.TileIllBeInAt(num5, tmpTicksToArrive, ticksAbs) : tile);
                bool  flag4           = CaravanNightRestUtility.WouldBeRestingAt(num6, num5);
                float progressPerTick = ForagedFoodPerDayCalculator.GetProgressPerTick(assumeCaravanMoving && !flag4, flag4);
                float num7            = 1f / progressPerTick;
                bool  flag5           = VirtualPlantsUtility.EnvironmentAllowsEatingVirtualPlantsAt(num6, num5);
                float num8            = num3 - num2;
                if (num8 > 0f)
                {
                    num4 += num8 * 60000f;
                    if (num4 >= num7)
                    {
                        BiomeDef biome       = worldGrid[num6].biome;
                        int      num9        = Mathf.RoundToInt(ForagedFoodPerDayCalculator.GetForagedFoodCountPerInterval(pawns, biome, faction));
                        ThingDef foragedFood = biome.foragedFood;
                        while (num4 >= num7)
                        {
                            num4 -= num7;
                            if (num9 <= 0)
                            {
                                continue;
                            }
                            bool flag6 = false;
                            for (int num10 = tmpFood.Count - 1; num10 >= 0; num10--)
                            {
                                ThingDefCount thingDefCount2 = tmpFood[num10];
                                if (thingDefCount2.ThingDef == foragedFood)
                                {
                                    tmpFood[num10] = thingDefCount2.WithCount(thingDefCount2.Count + num9);
                                    flag6          = true;
                                    break;
                                }
                            }
                            if (!flag6)
                            {
                                tmpFood.Add(new ThingDefCount(foragedFood, num9));
                            }
                        }
                    }
                }
                num2 = num3;
                int num11 = 0;
                for (int count8 = pawns.Count; num11 < count8; num11++)
                {
                    Pawn pawn3 = pawns[num11];
                    if (!pawn3.RaceProps.EatsFood)
                    {
                        continue;
                    }
                    if (flag5 && VirtualPlantsUtility.CanEverEatVirtualPlants(pawn3))
                    {
                        if (tmpDaysWorthOfFoodForPawn[num11] < num3)
                        {
                            tmpDaysWorthOfFoodForPawn[num11] = num3;
                        }
                        else
                        {
                            tmpDaysWorthOfFoodForPawn[num11] += 0.45f;
                        }
                        flag3 = true;
                    }
                    else
                    {
                        float num12 = cachedNutritionBetweenHungryAndFed[num11];
                        int   num13 = cachedTicksUntilHungryWhenFed[num11];
                        do
                        {
                            int num14 = BestEverEdibleFoodIndexFor(pawn3, tmpFood);
                            if (num14 < 0)
                            {
                                if (tmpDaysWorthOfFoodForPawn[num11] < num3)
                                {
                                    flag2 = true;
                                }
                                break;
                            }
                            ThingDefCount thingDefCount3 = tmpFood[num14];
                            float         num15          = Mathf.Min(thingDefCount3.ThingDef.ingestible.CachedNutrition, num12);
                            float         num16          = num15 / num12 * (float)num13 / 60000f;
                            int           num17          = Mathf.Min(Mathf.CeilToInt(Mathf.Min(0.2f, cachedMaxFoodLevel[num11]) / num15), thingDefCount3.Count);
                            tmpDaysWorthOfFoodForPawn[num11] += num16 * (float)num17;
                            tmpFood[num14] = thingDefCount3.WithCount(thingDefCount3.Count - num17);
                            flag3          = true;
                        }while (tmpDaysWorthOfFoodForPawn[num11] < num3);
                    }
                    if (flag2)
                    {
                        break;
                    }
                    num3 = Mathf.Max(num3, tmpDaysWorthOfFoodForPawn[num11]);
                }
            }while (!(!flag3 || flag2) && !(num3 > 601f));
            float num18 = 600f;
            int   num19 = 0;

            for (int count9 = pawns.Count; num19 < count9; num19++)
            {
                if (pawns[num19].RaceProps.EatsFood)
                {
                    num18 = Mathf.Min(num18, tmpDaysWorthOfFoodForPawn[num19]);
                }
            }
            return(num18);
        }
        private static float ApproxDaysWorthOfFood(List <Pawn> pawns, List <ThingCount> extraFood, bool assumeCanEatLocalPlants, IgnorePawnsInventoryMode ignoreInventory)
        {
            if (!DaysWorthOfFoodCalculator.AnyNonLocalPlantsEatingPawn(pawns, assumeCanEatLocalPlants))
            {
                return(1000f);
            }
            DaysWorthOfFoodCalculator.tmpFood.Clear();
            if (extraFood != null)
            {
                for (int i = 0; i < extraFood.Count; i++)
                {
                    if (extraFood[i].ThingDef.IsNutritionGivingIngestible && extraFood[i].Count > 0)
                    {
                        DaysWorthOfFoodCalculator.tmpFood.Add(extraFood[i]);
                    }
                }
            }
            for (int j = 0; j < pawns.Count; j++)
            {
                if (!InventoryCalculatorsUtility.ShouldIgnoreInventoryOf(pawns[j], ignoreInventory))
                {
                    ThingOwner <Thing> innerContainer = pawns[j].inventory.innerContainer;
                    for (int k = 0; k < innerContainer.Count; k++)
                    {
                        if (innerContainer[k].def.IsNutritionGivingIngestible)
                        {
                            DaysWorthOfFoodCalculator.tmpFood.Add(new ThingCount(innerContainer[k].def, innerContainer[k].stackCount));
                        }
                    }
                }
            }
            if (!DaysWorthOfFoodCalculator.tmpFood.Any())
            {
                return(0f);
            }
            DaysWorthOfFoodCalculator.tmpDaysWorthOfFoodPerPawn.Clear();
            DaysWorthOfFoodCalculator.tmpAnyFoodLeftIngestibleByPawn.Clear();
            for (int l = 0; l < pawns.Count; l++)
            {
                DaysWorthOfFoodCalculator.tmpDaysWorthOfFoodPerPawn.Add(0f);
                DaysWorthOfFoodCalculator.tmpAnyFoodLeftIngestibleByPawn.Add(true);
            }
            float num = 0f;

            while (true)
            {
                bool flag = false;
                for (int m = 0; m < pawns.Count; m++)
                {
                    Pawn pawn = pawns[m];
                    if (DaysWorthOfFoodCalculator.tmpAnyFoodLeftIngestibleByPawn[m] && pawn.RaceProps.EatsFood && (!assumeCanEatLocalPlants || !VirtualPlantsUtility.CanEverEatVirtualPlants(pawn)))
                    {
                        while (true)
                        {
                            int num2 = DaysWorthOfFoodCalculator.BestEverEdibleFoodIndexFor(pawns[m], DaysWorthOfFoodCalculator.tmpFood);
                            if (num2 < 0)
                            {
                                DaysWorthOfFoodCalculator.tmpAnyFoodLeftIngestibleByPawn[m] = false;
                                break;
                            }
                            float        num3 = Mathf.Min(DaysWorthOfFoodCalculator.tmpFood[num2].ThingDef.ingestible.nutrition, pawn.needs.food.NutritionBetweenHungryAndFed);
                            float        num4 = (float)(num3 / pawn.needs.food.NutritionBetweenHungryAndFed * (float)pawn.needs.food.TicksUntilHungryWhenFed / 60000.0);
                            List <float> list;
                            int          index;
                            (list = DaysWorthOfFoodCalculator.tmpDaysWorthOfFoodPerPawn)[index = m] = list[index] + num4;
                            DaysWorthOfFoodCalculator.tmpFood[num2] = DaysWorthOfFoodCalculator.tmpFood[num2].WithCount(DaysWorthOfFoodCalculator.tmpFood[num2].Count - 1);
                            flag = true;
                            if (!(DaysWorthOfFoodCalculator.tmpDaysWorthOfFoodPerPawn[m] < num))
                            {
                                break;
                            }
                        }
                        num = Mathf.Max(num, DaysWorthOfFoodCalculator.tmpDaysWorthOfFoodPerPawn[m]);
                    }
                }
                if (!flag)
                {
                    break;
                }
            }
            float num5 = 1000f;

            for (int n = 0; n < pawns.Count; n++)
            {
                if (pawns[n].RaceProps.EatsFood && (!assumeCanEatLocalPlants || !VirtualPlantsUtility.CanEverEatVirtualPlants(pawns[n])))
                {
                    num5 = Mathf.Min(num5, DaysWorthOfFoodCalculator.tmpDaysWorthOfFoodPerPawn[n]);
                }
            }
            return(num5);
        }
Beispiel #20
0
        public static void DrawCaravanInfo(CaravanUIUtility.CaravanInfo info, CaravanUIUtility.CaravanInfo?info2, int currentTile, int?ticksToArrive, float lastMassFlashTime, Rect rect, bool lerpMassColor = true, string extraDaysWorthOfFoodTipInfo = null, bool multiline = false)
        {
            CaravanUIUtility.tmpInfo.Clear();
            string value = string.Concat(new string[]
            {
                info.massUsage.ToStringEnsureThreshold(info.massCapacity, 0),
                " / ",
                info.massCapacity.ToString("F0"),
                " ",
                "kg".Translate()
            });
            string secondValue = (!info2.HasValue) ? null : string.Concat(new string[]
            {
                info2.Value.massUsage.ToStringEnsureThreshold(info2.Value.massCapacity, 0),
                " / ",
                info2.Value.massCapacity.ToString("F0"),
                " ",
                "kg".Translate()
            });

            CaravanUIUtility.tmpInfo.Add(new TransferableUIUtility.ExtraInfo("Mass".Translate(), value, CaravanUIUtility.GetMassColor(info.massUsage, info.massCapacity, lerpMassColor), CaravanUIUtility.GetMassTip(info.massUsage, info.massCapacity, info.massCapacityExplanation, (!info2.HasValue) ? null : new float?(info2.Value.massUsage), (!info2.HasValue) ? null : new float?(info2.Value.massCapacity), (!info2.HasValue) ? null : info2.Value.massCapacityExplanation), secondValue, (!info2.HasValue) ? Color.white : CaravanUIUtility.GetMassColor(info2.Value.massUsage, info2.Value.massCapacity, lerpMassColor), lastMassFlashTime));
            if (info.extraMassUsage != -1f)
            {
                string value2 = string.Concat(new string[]
                {
                    info.extraMassUsage.ToStringEnsureThreshold(info.extraMassCapacity, 0),
                    " / ",
                    info.extraMassCapacity.ToString("F0"),
                    " ",
                    "kg".Translate()
                });
                string secondValue2 = (!info2.HasValue) ? null : string.Concat(new string[]
                {
                    info2.Value.extraMassUsage.ToStringEnsureThreshold(info2.Value.extraMassCapacity, 0),
                    " / ",
                    info2.Value.extraMassCapacity.ToString("F0"),
                    " ",
                    "kg".Translate()
                });
                CaravanUIUtility.tmpInfo.Add(new TransferableUIUtility.ExtraInfo("CaravanMass".Translate(), value2, CaravanUIUtility.GetMassColor(info.extraMassUsage, info.extraMassCapacity, true), CaravanUIUtility.GetMassTip(info.extraMassUsage, info.extraMassCapacity, info.extraMassCapacityExplanation, (!info2.HasValue) ? null : new float?(info2.Value.extraMassUsage), (!info2.HasValue) ? null : new float?(info2.Value.extraMassCapacity), (!info2.HasValue) ? null : info2.Value.extraMassCapacityExplanation), secondValue2, (!info2.HasValue) ? Color.white : CaravanUIUtility.GetMassColor(info2.Value.extraMassUsage, info2.Value.extraMassCapacity, true), -9999f));
            }
            string text = "CaravanMovementSpeedTip".Translate();

            if (!info.tilesPerDayExplanation.NullOrEmpty())
            {
                text = text + "\n\n" + info.tilesPerDayExplanation;
            }
            if (info2.HasValue && !info2.Value.tilesPerDayExplanation.NullOrEmpty())
            {
                text = text + "\n\n-----\n\n" + info2.Value.tilesPerDayExplanation;
            }
            CaravanUIUtility.tmpInfo.Add(new TransferableUIUtility.ExtraInfo("CaravanMovementSpeed".Translate(), info.tilesPerDay.ToString("0.#") + " " + "TilesPerDay".Translate(), GenUI.LerpColor(CaravanUIUtility.TilesPerDayColor, info.tilesPerDay), text, (!info2.HasValue) ? null : (info2.Value.tilesPerDay.ToString("0.#") + " " + "TilesPerDay".Translate()), (!info2.HasValue) ? Color.white : GenUI.LerpColor(CaravanUIUtility.TilesPerDayColor, info2.Value.tilesPerDay), -9999f));
            CaravanUIUtility.tmpInfo.Add(new TransferableUIUtility.ExtraInfo("DaysWorthOfFood".Translate(), CaravanUIUtility.GetDaysWorthOfFoodLabel(info.daysWorthOfFood, multiline), CaravanUIUtility.GetDaysWorthOfFoodColor(info.daysWorthOfFood, ticksToArrive), "DaysWorthOfFoodTooltip".Translate() + extraDaysWorthOfFoodTipInfo + "\n\n" + VirtualPlantsUtility.GetVirtualPlantsStatusExplanationAt(currentTile, Find.TickManager.TicksAbs), (!info2.HasValue) ? null : CaravanUIUtility.GetDaysWorthOfFoodLabel(info2.Value.daysWorthOfFood, multiline), (!info2.HasValue) ? Color.white : CaravanUIUtility.GetDaysWorthOfFoodColor(info2.Value.daysWorthOfFood, ticksToArrive), -9999f));
            string text2 = info.foragedFoodPerDay.Second.ToString("0.#");
            string text3 = (!info2.HasValue) ? null : info2.Value.foragedFoodPerDay.Second.ToString("0.#");
            string text4 = "ForagedFoodPerDayTip".Translate();

            text4 = text4 + "\n\n" + info.foragedFoodPerDayExplanation;
            if (info2.HasValue)
            {
                text4 = text4 + "\n\n-----\n\n" + info2.Value.foragedFoodPerDayExplanation;
            }
            if (info.foragedFoodPerDay.Second > 0f || (info2.HasValue && info2.Value.foragedFoodPerDay.Second > 0f))
            {
                string text5 = (!multiline) ? " " : "\n";
                if (!info2.HasValue)
                {
                    string text6 = text2;
                    text2 = string.Concat(new string[]
                    {
                        text6,
                        text5,
                        "(",
                        info.foragedFoodPerDay.First.label,
                        ")"
                    });
                }
                else
                {
                    string text6 = text3;
                    text3 = string.Concat(new string[]
                    {
                        text6,
                        text5,
                        "(",
                        info2.Value.foragedFoodPerDay.First.label.Truncate(50f, null),
                        ")"
                    });
                }
            }
            CaravanUIUtility.tmpInfo.Add(new TransferableUIUtility.ExtraInfo("ForagedFoodPerDay".Translate(), text2, Color.white, text4, text3, Color.white, -9999f));
            string text7 = "CaravanVisibilityTip".Translate();

            if (!info.visibilityExplanation.NullOrEmpty())
            {
                text7 = text7 + "\n\n" + info.visibilityExplanation;
            }
            if (info2.HasValue && !info2.Value.visibilityExplanation.NullOrEmpty())
            {
                text7 = text7 + "\n\n-----\n\n" + info2.Value.visibilityExplanation;
            }
            CaravanUIUtility.tmpInfo.Add(new TransferableUIUtility.ExtraInfo("Visibility".Translate(), info.visibility.ToStringPercent(), GenUI.LerpColor(CaravanUIUtility.VisibilityColor, info.visibility), text7, (!info2.HasValue) ? null : info2.Value.visibility.ToStringPercent(), (!info2.HasValue) ? Color.white : GenUI.LerpColor(CaravanUIUtility.VisibilityColor, info2.Value.visibility), -9999f));
            TransferableUIUtility.DrawExtraInfo(CaravanUIUtility.tmpInfo, rect);
        }
 public static bool CanEatVirtualPlants(Pawn p, int ticksAbs)
 {
     return(p.Tile >= 0 && !p.Dead && p.IsWorldPawn() && VirtualPlantsUtility.CanEverEatVirtualPlants(p) && VirtualPlantsUtility.EnvironmentAllowsEatingVirtualPlantsAt(p.Tile, ticksAbs));
 }
Beispiel #22
0
        protected override void FillTab()
        {
            Rect rect  = new Rect(0f, 0f, WITab_Terrain.WinSize.x, WITab_Terrain.WinSize.y).ContractedBy(10f);
            Rect rect2 = rect;

            Text.Font = GameFont.Medium;
            Widgets.Label(rect2, base.SelTile.biome.LabelCap);
            Rect rect3 = rect;

            rect3.yMin += 35f;
            Text.Font   = GameFont.Small;
            Listing_Standard listing_Standard = new Listing_Standard();

            listing_Standard.verticalSpacing = 0f;
            listing_Standard.Begin(rect3);
            Tile  selTile   = base.SelTile;
            int   selTileID = base.SelTileID;
            float y         = Find.WorldGrid.LongLatOf(selTileID).y;

            listing_Standard.Label(selTile.biome.description, -1f);
            listing_Standard.Gap(8f);
            listing_Standard.GapLine(12f);
            if (!selTile.biome.implemented)
            {
                listing_Standard.Label(selTile.biome.LabelCap + " " + "BiomeNotImplemented".Translate(), -1f);
            }
            listing_Standard.LabelDouble("Terrain".Translate(), selTile.hilliness.GetLabelCap());
            if (selTile.VisibleRoads != null)
            {
                listing_Standard.LabelDouble("Road".Translate(), GenText.ToCommaList((from roadlink in selTile.VisibleRoads
                                                                                      select roadlink.road.label).Distinct <string>(), true).CapitalizeFirst());
            }
            if (selTile.VisibleRivers != null)
            {
                listing_Standard.LabelDouble("River".Translate(), selTile.VisibleRivers.MaxBy((Tile.RiverLink riverlink) => riverlink.river.degradeThreshold).river.LabelCap);
            }
            if (!Find.World.Impassable(selTileID))
            {
                int num      = 2500;
                int numTicks = Mathf.Min(num + WorldPathGrid.CalculatedCostAt(selTileID, false, -1f), 120000);
                listing_Standard.LabelDouble("MovementTimeNow".Translate(), numTicks.ToStringTicksToPeriod(true, false, true));
                int numTicks2 = Mathf.Min(num + WorldPathGrid.CalculatedCostAt(selTileID, false, Season.Summer.GetMiddleYearPct(y)), 120000);
                listing_Standard.LabelDouble("MovementTimeSummer".Translate(), numTicks2.ToStringTicksToPeriod(true, false, true));
                int numTicks3 = Mathf.Min(num + WorldPathGrid.CalculatedCostAt(selTileID, false, Season.Winter.GetMiddleYearPct(y)), 120000);
                listing_Standard.LabelDouble("MovementTimeWinter".Translate(), numTicks3.ToStringTicksToPeriod(true, false, true));
            }
            if (selTile.biome.canBuildBase)
            {
                listing_Standard.LabelDouble("StoneTypesHere".Translate(), GenText.ToCommaList(from rt in Find.World.NaturalRockTypesIn(selTileID)
                                                                                               select rt.label, true).CapitalizeFirst());
            }
            listing_Standard.LabelDouble("Elevation".Translate(), selTile.elevation.ToString("F0") + "m");
            listing_Standard.GapLine(12f);
            listing_Standard.LabelDouble("AvgTemp".Translate(), selTile.temperature.ToStringTemperature("F1"));
            float celsiusTemp = GenTemperature.AverageTemperatureAtTileForTwelfth(selTileID, Season.Winter.GetMiddleTwelfth(y));

            listing_Standard.LabelDouble("AvgWinterTemp".Translate(), celsiusTemp.ToStringTemperature("F1"));
            float celsiusTemp2 = GenTemperature.AverageTemperatureAtTileForTwelfth(selTileID, Season.Summer.GetMiddleTwelfth(y));

            listing_Standard.LabelDouble("AvgSummerTemp".Translate(), celsiusTemp2.ToStringTemperature("F1"));
            listing_Standard.LabelDouble("OutdoorGrowingPeriod".Translate(), Zone_Growing.GrowingQuadrumsDescription(selTileID));
            listing_Standard.LabelDouble("Rainfall".Translate(), selTile.rainfall.ToString("F0") + "mm");
            listing_Standard.LabelDouble("AnimalsCanGrazeNow".Translate(), (!VirtualPlantsUtility.EnvironmentAllowsEatingVirtualPlantsNowAt(selTileID)) ? "No".Translate() : "Yes".Translate());
            listing_Standard.GapLine(12f);
            listing_Standard.LabelDouble("AverageDiseaseFrequency".Translate(), string.Format("{0} {1}", (60f / selTile.biome.diseaseMtbDays).ToString("F1"), "PerYear".Translate()));
            listing_Standard.LabelDouble("TimeZone".Translate(), GenDate.TimeZoneAt(Find.WorldGrid.LongLatOf(selTileID).x).ToStringWithSign());
            StringBuilder stringBuilder = new StringBuilder();
            Rot4          rot           = Find.World.CoastDirectionAt(selTileID);

            if (rot.IsValid)
            {
                stringBuilder.AppendWithComma(("HasCoast" + rot.ToString()).Translate());
            }
            if (Find.World.HasCaves(selTileID))
            {
                stringBuilder.AppendWithComma("HasCaves".Translate());
            }
            if (stringBuilder.Length > 0)
            {
                listing_Standard.LabelDouble("SpecialFeatures".Translate(), stringBuilder.ToString().CapitalizeFirst());
            }
            if (Prefs.DevMode)
            {
                listing_Standard.LabelDouble("Debug world tile ID", selTileID.ToString());
            }
            listing_Standard.End();
        }