public static float ApproxDaysUntilRotLeftAfterTradeableTransfer(List <Thing> allCurrentThings, List <Tradeable> tradeables, int tile, IgnorePawnsInventoryMode ignoreInventory)
        {
            DaysUntilRotCalculator.tmpThingCountsFromTradeables.Clear();
            TransferableUtility.SimulateTradeableTransfer(allCurrentThings, tradeables, DaysUntilRotCalculator.tmpThingCountsFromTradeables);
            DaysUntilRotCalculator.tmpThingCounts.Clear();
            for (int i = DaysUntilRotCalculator.tmpThingCountsFromTradeables.Count - 1; i >= 0; i--)
            {
                if (DaysUntilRotCalculator.tmpThingCountsFromTradeables[i].Count > 0)
                {
                    Pawn pawn = DaysUntilRotCalculator.tmpThingCountsFromTradeables[i].Thing as Pawn;
                    if (pawn != null)
                    {
                        if (!InventoryCalculatorsUtility.ShouldIgnoreInventoryOf(pawn, ignoreInventory))
                        {
                            ThingOwner <Thing> innerContainer = pawn.inventory.innerContainer;
                            for (int j = 0; j < innerContainer.Count; j++)
                            {
                                DaysUntilRotCalculator.tmpThingCounts.Add(new ThingCount(innerContainer[j], innerContainer[j].stackCount));
                            }
                        }
                    }
                    else
                    {
                        DaysUntilRotCalculator.tmpThingCounts.Add(DaysUntilRotCalculator.tmpThingCountsFromTradeables[i]);
                    }
                }
            }
            DaysUntilRotCalculator.tmpThingCountsFromTradeables.Clear();
            float result = DaysUntilRotCalculator.ApproxDaysUntilRot(DaysUntilRotCalculator.tmpThingCounts, tile, null, 0f, 3300);

            DaysUntilRotCalculator.tmpThingCounts.Clear();
            return(result);
        }
        public static float ApproxDaysUntilRotLeftAfterTransfer(List <TransferableOneWay> transferables, int assumingTile, IgnorePawnsInventoryMode ignoreInventory)
        {
            DaysUntilRotCalculator.tmpThings.Clear();
            for (int i = 0; i < transferables.Count; i++)
            {
                TransferableOneWay transferableOneWay = transferables[i];
                if (transferableOneWay.HasAnyThing)
                {
                    if (transferableOneWay.AnyThing is Pawn)
                    {
                        for (int j = transferableOneWay.things.Count - 1; j >= transferableOneWay.CountToTransfer; j--)
                        {
                            Pawn pawn = (Pawn)transferableOneWay.things[j];
                            if (!InventoryCalculatorsUtility.ShouldIgnoreInventoryOf(pawn, ignoreInventory))
                            {
                                ThingOwner <Thing> innerContainer = pawn.inventory.innerContainer;
                                for (int k = 0; k < innerContainer.Count; k++)
                                {
                                    DaysUntilRotCalculator.tmpThings.Add(innerContainer[k]);
                                }
                            }
                        }
                    }
                    else if (transferableOneWay.MaxCount - transferableOneWay.CountToTransfer > 0)
                    {
                        DaysUntilRotCalculator.tmpThings.AddRange(transferableOneWay.things);
                    }
                }
            }
            float result = DaysUntilRotCalculator.ApproxDaysUntilRot(DaysUntilRotCalculator.tmpThings, assumingTile);

            DaysUntilRotCalculator.tmpThings.Clear();
            return(result);
        }
예제 #3
0
        public static float ApproxDaysUntilRotLeftAfterTradeableTransfer(List <Thing> allCurrentThings, List <Tradeable> tradeables, int tile, IgnorePawnsInventoryMode ignoreInventory)
        {
            tmpThingCountsFromTradeables.Clear();
            TransferableUtility.SimulateTradeableTransfer(allCurrentThings, tradeables, tmpThingCountsFromTradeables);
            tmpThingCounts.Clear();
            for (int num = tmpThingCountsFromTradeables.Count - 1; num >= 0; num--)
            {
                if (tmpThingCountsFromTradeables[num].Count > 0)
                {
                    Pawn pawn = tmpThingCountsFromTradeables[num].Thing as Pawn;
                    if (pawn != null)
                    {
                        if (!InventoryCalculatorsUtility.ShouldIgnoreInventoryOf(pawn, ignoreInventory))
                        {
                            ThingOwner <Thing> innerContainer = pawn.inventory.innerContainer;
                            for (int i = 0; i < innerContainer.Count; i++)
                            {
                                tmpThingCounts.Add(new ThingCount(innerContainer[i], innerContainer[i].stackCount));
                            }
                        }
                    }
                    else
                    {
                        tmpThingCounts.Add(tmpThingCountsFromTradeables[num]);
                    }
                }
            }
            tmpThingCountsFromTradeables.Clear();
            float result = ApproxDaysUntilRot(tmpThingCounts, tile);

            tmpThingCounts.Clear();
            return(result);
        }
        public static float ApproxDaysUntilRotLeftAfterTradeableTransfer(List <Thing> allCurrentThings, List <Tradeable> tradeables, int assumingTile, IgnorePawnsInventoryMode ignoreInventory)
        {
            TransferableUtility.SimulateTradeableTransfer(allCurrentThings, tradeables, DaysUntilRotCalculator.tmpThingStackParts);
            DaysUntilRotCalculator.tmpThings.Clear();
            for (int num = DaysUntilRotCalculator.tmpThingStackParts.Count - 1; num >= 0; num--)
            {
                if (DaysUntilRotCalculator.tmpThingStackParts[num].Count > 0)
                {
                    Pawn pawn = DaysUntilRotCalculator.tmpThingStackParts[num].Thing as Pawn;
                    if (pawn != null)
                    {
                        if (!InventoryCalculatorsUtility.ShouldIgnoreInventoryOf(pawn, ignoreInventory))
                        {
                            ThingOwner <Thing> innerContainer = pawn.inventory.innerContainer;
                            for (int i = 0; i < innerContainer.Count; i++)
                            {
                                DaysUntilRotCalculator.tmpThings.Add(innerContainer[i]);
                            }
                        }
                    }
                    else
                    {
                        DaysUntilRotCalculator.tmpThings.Add(DaysUntilRotCalculator.tmpThingStackParts[num].Thing);
                    }
                }
            }
            DaysUntilRotCalculator.tmpThingStackParts.Clear();
            float result = DaysUntilRotCalculator.ApproxDaysUntilRot(DaysUntilRotCalculator.tmpThings, assumingTile);

            DaysUntilRotCalculator.tmpThings.Clear();
            return(result);
        }
예제 #5
0
        public static float ApproxDaysUntilRotLeftAfterTransfer(List <TransferableOneWay> transferables, int tile, IgnorePawnsInventoryMode ignoreInventory, WorldPath path = null, float nextTileCostLeft = 0f, int caravanTicksPerMove = 3300)
        {
            tmpThingCounts.Clear();
            for (int i = 0; i < transferables.Count; i++)
            {
                TransferableOneWay transferableOneWay = transferables[i];
                if (!transferableOneWay.HasAnyThing)
                {
                    continue;
                }
                if (transferableOneWay.AnyThing is Pawn)
                {
                    for (int num = transferableOneWay.things.Count - 1; num >= transferableOneWay.CountToTransfer; num--)
                    {
                        Pawn pawn = (Pawn)transferableOneWay.things[num];
                        if (!InventoryCalculatorsUtility.ShouldIgnoreInventoryOf(pawn, ignoreInventory))
                        {
                            ThingOwner <Thing> innerContainer = pawn.inventory.innerContainer;
                            for (int j = 0; j < innerContainer.Count; j++)
                            {
                                tmpThingCounts.Add(new ThingCount(innerContainer[j], innerContainer[j].stackCount));
                            }
                        }
                    }
                }
                else if (transferableOneWay.MaxCount - transferableOneWay.CountToTransfer > 0)
                {
                    thingsInReverse.Clear();
                    thingsInReverse.AddRange(transferableOneWay.things);
                    thingsInReverse.Reverse();
                    TransferableUtility.TransferNoSplit(thingsInReverse, transferableOneWay.MaxCount - transferableOneWay.CountToTransfer, delegate(Thing thing, int count)
                    {
                        tmpThingCounts.Add(new ThingCount(thing, count));
                    }, removeIfTakingEntireThing: false, errorIfNotEnoughThings: false);
                }
            }
            thingsInReverse.Clear();
            float result = ApproxDaysUntilRot(tmpThingCounts, tile, path, nextTileCostLeft, caravanTicksPerMove);

            tmpThingCounts.Clear();
            return(result);
        }
        public static float ApproxDaysUntilRotLeftAfterTransfer(List <TransferableOneWay> transferables, int tile, IgnorePawnsInventoryMode ignoreInventory, WorldPath path = null, float nextTileCostLeft = 0f, int caravanTicksPerMove = 3300)
        {
            DaysUntilRotCalculator.tmpThingCounts.Clear();
            for (int i = 0; i < transferables.Count; i++)
            {
                TransferableOneWay transferableOneWay = transferables[i];
                if (transferableOneWay.HasAnyThing)
                {
                    if (transferableOneWay.AnyThing is Pawn)
                    {
                        for (int j = transferableOneWay.things.Count - 1; j >= transferableOneWay.CountToTransfer; j--)
                        {
                            Pawn pawn = (Pawn)transferableOneWay.things[j];
                            if (!InventoryCalculatorsUtility.ShouldIgnoreInventoryOf(pawn, ignoreInventory))
                            {
                                ThingOwner <Thing> innerContainer = pawn.inventory.innerContainer;
                                for (int k = 0; k < innerContainer.Count; k++)
                                {
                                    DaysUntilRotCalculator.tmpThingCounts.Add(new ThingCount(innerContainer[k], innerContainer[k].stackCount));
                                }
                            }
                        }
                    }
                    else if (transferableOneWay.MaxCount - transferableOneWay.CountToTransfer > 0)
                    {
                        DaysUntilRotCalculator.thingsInReverse.Clear();
                        DaysUntilRotCalculator.thingsInReverse.AddRange(transferableOneWay.things);
                        DaysUntilRotCalculator.thingsInReverse.Reverse();
                        TransferableUtility.TransferNoSplit(DaysUntilRotCalculator.thingsInReverse, transferableOneWay.MaxCount - transferableOneWay.CountToTransfer, delegate(Thing thing, int count)
                        {
                            DaysUntilRotCalculator.tmpThingCounts.Add(new ThingCount(thing, count));
                        }, false, false);
                    }
                }
            }
            DaysUntilRotCalculator.thingsInReverse.Clear();
            float result = DaysUntilRotCalculator.ApproxDaysUntilRot(DaysUntilRotCalculator.tmpThingCounts, tile, path, nextTileCostLeft, caravanTicksPerMove);

            DaysUntilRotCalculator.tmpThingCounts.Clear();
            return(result);
        }
예제 #7
0
        private float GetMass(Thing thing)
        {
            if (thing == null)
            {
                return(0f);
            }
            float num = thing.GetStatValue(StatDefOf.Mass, true);

            if (thing is Pawn pawn)
            {
                if (InventoryCalculatorsUtility.ShouldIgnoreInventoryOf(pawn, ignorePawnInventoryMass))
                {
                    num -= MassUtility.InventoryMass(pawn);
                }
            }
            else if (ignoreSpawnedCorpseGearAndInventoryMass)
            {
                if (thing is Corpse corpse && corpse.Spawned)
                {
                    num -= MassUtility.GearAndInventoryMass(corpse.InnerPawn);
                }
            }
            return(num);
        }
        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);
        }
예제 #9
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 ApproxDaysWorthOfWater(List <Pawn> pawns, List <ThingCount> extraWater, IgnorePawnsInventoryMode ignoreInventory)
        {
            if (!DaysWorthOfWaterCalculator.AnyNonTerrainDrinkingPawn(pawns))
            {
                return(1000f);
            }
            List <ThingCount> tmpWater = new List <ThingCount>();

            tmpWater.Clear();
            if (extraWater != null)
            {
                for (int i = 0; i < extraWater.Count; i++)
                {
                    bool canGetWater = false;
                    for (int j = 0; j < extraWater[i].ThingDef.comps.Count; j++)
                    {
                        var compprop = extraWater[i].ThingDef.comps[j] as CompProperties_WaterSource;
                        if (compprop != null && compprop.sourceType == CompProperties_WaterSource.SourceType.Item && compprop.waterAmount > 0.0f)
                        {
                            canGetWater = true;
                            break;
                        }
                    }
                    if (canGetWater && extraWater[i].Count > 0)
                    {
                        tmpWater.Add(extraWater[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].CanGetWater())
                        {
                            tmpWater.Add(new ThingCount(innerContainer[k].def, innerContainer[k].stackCount));
                        }
                    }
                }
            }
            if (!tmpWater.Any <ThingCount>())
            {
                return(0f);
            }
            List <float> tmpDaysWorthOfFoodPerPawn      = new List <float>();
            List <bool>  tmpAnyFoodLeftIngestibleByPawn = new List <bool>();

            tmpDaysWorthOfFoodPerPawn.Clear();
            tmpAnyFoodLeftIngestibleByPawn.Clear();
            for (int l = 0; l < pawns.Count; l++)
            {
                tmpDaysWorthOfFoodPerPawn.Add(0f);
                tmpAnyFoodLeftIngestibleByPawn.Add(true);
            }
            float num = 0f;
            bool  flag;

            do
            {
                flag = false;
                for (int m = 0; m < pawns.Count; m++)
                {
                    Pawn pawn = pawns[m];
                    if (tmpAnyFoodLeftIngestibleByPawn[m])
                    {
                        do
                        {
                            int num2 = DaysWorthOfWaterCalculator.BestEverGetWaterIndexFor(pawns[m], tmpWater);
                            if (num2 < 0)
                            {
                                tmpAnyFoodLeftIngestibleByPawn[m] = false;
                                break;
                            }
                            CompProperties_WaterSource compprop = null;
                            for (int x = 0; x < tmpWater[num2].ThingDef.comps.Count; x++)
                            {
                                compprop = tmpWater[num2].ThingDef.comps[x] as CompProperties_WaterSource;
                                if (compprop != null && compprop.sourceType == CompProperties_WaterSource.SourceType.Item)
                                {
                                    break;
                                }
                            }
                            if (compprop == null)
                            {
                                tmpAnyFoodLeftIngestibleByPawn[m] = false;
                                break;
                            }
                            Need_Water need_water = pawn.needs.water();
                            if (need_water == null)
                            {
                                tmpAnyFoodLeftIngestibleByPawn[m] = false;
                                break;
                            }
                            float num3 = Mathf.Min(compprop.waterAmount, need_water.WaterAmountBetweenThirstyAndHealthy);
                            float num4 = num3 / need_water.WaterAmountBetweenThirstyAndHealthy * (float)need_water.TicksUntilThirstyWhenHealthy / 60000f;
                            tmpDaysWorthOfFoodPerPawn[m] = tmpDaysWorthOfFoodPerPawn[m] + num4;
                            tmpWater[num2] = tmpWater[num2].WithCount(tmpWater[num2].Count - 1);
                            flag           = true;
                        }while (tmpDaysWorthOfFoodPerPawn[m] < num);
                        num = Mathf.Max(num, tmpDaysWorthOfFoodPerPawn[m]);
                    }
                }
            }while (flag);
            float num6 = 1000f;

            for (int n = 0; n < pawns.Count; n++)
            {
                num6 = Mathf.Min(num6, tmpDaysWorthOfFoodPerPawn[n]);
            }
            return(num6);
        }
        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);
        }
예제 #12
0
        private void DrawMass(Rect rect, TransferableOneWay trad, float availableMass)
        {
            if (!trad.HasAnyThing)
            {
                return;
            }
            Thing anyThing = trad.AnyThing;
            Pawn  pawn     = anyThing as Pawn;

            if (pawn != null && !includePawnsMassInMassUsage && !MassUtility.CanEverCarryAnything(pawn))
            {
                return;
            }
            Widgets.DrawHighlightIfMouseover(rect);
            if (pawn == null || includePawnsMassInMassUsage)
            {
                float mass = GetMass(anyThing);
                if (Mouse.IsOver(rect))
                {
                    if (pawn != null)
                    {
                        float gearMass = 0f;
                        float invMass  = 0f;
                        gearMass = MassUtility.GearMass(pawn);
                        if (!InventoryCalculatorsUtility.ShouldIgnoreInventoryOf(pawn, ignorePawnInventoryMass))
                        {
                            invMass = MassUtility.InventoryMass(pawn);
                        }
                        TooltipHandler.TipRegion(rect, () => GetPawnMassTip(trad, 0f, mass - gearMass - invMass, gearMass, invMass), trad.GetHashCode() * 59);
                    }
                    else
                    {
                        TooltipHandler.TipRegion(rect, "ItemWeightTip".Translate());
                    }
                }
                if (mass > availableMass)
                {
                    GUI.color = ColoredText.RedReadable;
                }
                else
                {
                    GUI.color = TransferableOneWayWidget.ItemMassColor;
                }
                Widgets.Label(rect, mass.ToStringMass());
            }
            else
            {
                float cap      = MassUtility.Capacity(pawn, null);
                float gearMass = MassUtility.GearMass(pawn);
                float invMass  = InventoryCalculatorsUtility.ShouldIgnoreInventoryOf(pawn, ignorePawnInventoryMass) ? 0f : MassUtility.InventoryMass(pawn);
                float num      = cap - gearMass - invMass;
                if (num > 0f)
                {
                    GUI.color = Color.green;
                }
                else if (num < 0f)
                {
                    GUI.color = ColoredText.RedReadable;
                }
                else
                {
                    GUI.color = Color.gray;
                }
                Widgets.Label(rect, num.ToStringMassOffset());
                if (Mouse.IsOver(rect))
                {
                    TooltipHandler.TipRegion(rect, () => GetPawnMassTip(trad, cap, 0f, gearMass, invMass), trad.GetHashCode() * 59);
                }
            }
            GUI.color = Color.white;
        }
        private static float ApproxDaysWorthOfWater(
            List <Pawn> pawns,
            List <ThingDefCount> extraWater,
            IgnorePawnsInventoryMode ignoreInventory)
        {
            if (!AnyNonTerrainDrinkingPawn(pawns))
            {
                return(1000f);
            }

            var tmpWater = new List <ThingDefCount>();

            tmpWater.Clear();

            if (extraWater != null)
            {
                foreach (var thingDefCount in extraWater)
                {
                    var canGetWater = false;
                    foreach (var compProperties in thingDefCount.ThingDef.comps)
                    {
                        if (!(compProperties is CompProperties_WaterSource compprop) ||
                            compprop.sourceType != CompProperties_WaterSource.SourceType.Item ||
                            !(compprop.waterAmount > 0.0f))
                        {
                            continue;
                        }

                        canGetWater = true;
                        break;
                    }

                    if (canGetWater && thingDefCount.Count > 0)
                    {
                        tmpWater.Add(thingDefCount);
                    }
                }
            }

            foreach (var pawn in pawns)
            {
                if (InventoryCalculatorsUtility.ShouldIgnoreInventoryOf(pawn, ignoreInventory))
                {
                    continue;
                }

                var innerContainer = pawn.inventory.innerContainer;
                foreach (var thing in innerContainer)
                {
                    if (thing.CanGetWater())
                    {
                        tmpWater.Add(new ThingDefCount(thing.def, thing.stackCount));
                    }
                }
            }

            if (!tmpWater.Any())
            {
                return(0f);
            }

            var tmpDaysWorthOfFoodPerPawn      = new List <float>();
            var tmpAnyFoodLeftIngestibleByPawn = new List <bool>();

            tmpDaysWorthOfFoodPerPawn.Clear();
            tmpAnyFoodLeftIngestibleByPawn.Clear();
            for (var l = 0; l < pawns.Count; l++)
            {
                tmpDaysWorthOfFoodPerPawn.Add(0f);
                tmpAnyFoodLeftIngestibleByPawn.Add(true);
            }

            var  num = 0f;
            bool flag;

            do
            {
                flag = false;
                for (var m = 0; m < pawns.Count; m++)
                {
                    var pawn = pawns[m];
                    if (!tmpAnyFoodLeftIngestibleByPawn[m])
                    {
                        continue;
                    }

                    do
                    {
                        var num2 = BestEverGetWaterIndexFor(tmpWater);
                        if (num2 < 0)
                        {
                            tmpAnyFoodLeftIngestibleByPawn[m] = false;
                            break;
                        }

                        CompProperties_WaterSource compprop = null;
                        foreach (var compProperties in tmpWater[num2].ThingDef.comps)
                        {
                            compprop = compProperties as CompProperties_WaterSource;
                            if (compprop != null && compprop.sourceType == CompProperties_WaterSource.SourceType.Item)
                            {
                                break;
                            }
                        }

                        if (compprop == null)
                        {
                            tmpAnyFoodLeftIngestibleByPawn[m] = false;
                            break;
                        }

                        var need_water = pawn.needs.Water();
                        if (need_water == null)
                        {
                            tmpAnyFoodLeftIngestibleByPawn[m] = false;
                            break;
                        }

                        var num3 = Mathf.Min(compprop.waterAmount, need_water.WaterAmountBetweenThirstyAndHealthy);
                        var num4 = num3 / need_water.WaterAmountBetweenThirstyAndHealthy
                                   * need_water.TicksUntilThirstyWhenHealthy / 60000f;
                        tmpDaysWorthOfFoodPerPawn[m] = tmpDaysWorthOfFoodPerPawn[m] + num4;
                        tmpWater[num2] = tmpWater[num2].WithCount(tmpWater[num2].Count - 1);
                        flag           = true;
                    }while (tmpDaysWorthOfFoodPerPawn[m] < num);

                    num = Mathf.Max(num, tmpDaysWorthOfFoodPerPawn[m]);
                }
            }while (flag);

            var num6 = 1000f;

            for (var n = 0; n < pawns.Count; n++)
            {
                num6 = Mathf.Min(num6, tmpDaysWorthOfFoodPerPawn[n]);
            }

            return(num6);
        }