private void TrySatisfyPawnNeeds(Pawn pawn)
        {
            if (pawn.Dead)
            {
                return;
            }
            List <Need> allNeeds = pawn.needs.AllNeeds;

            for (int i = 0; i < allNeeds.Count; i++)
            {
                Need          need          = allNeeds[i];
                Need_Rest     need_Rest     = need as Need_Rest;
                Need_Food     need_Food     = need as Need_Food;
                Need_Chemical need_Chemical = need as Need_Chemical;
                Need_Joy      need_Joy      = need as Need_Joy;
                if (need_Rest != null)
                {
                    TrySatisfyRestNeed(pawn, need_Rest);
                }
                else if (need_Food != null)
                {
                    TrySatisfyFoodNeed(pawn, need_Food);
                }
                else if (need_Chemical != null)
                {
                    TrySatisfyChemicalNeed(pawn, need_Chemical);
                }
                else if (need_Joy != null)
                {
                    TrySatisfyJoyNeed(pawn, need_Joy);
                }
            }
        }
示例#2
0
        // RimWorld.Planet.CaravanPawnsNeedsUtility
        public static void TrySatisfyFoodNeed(Pawn pawn, Need_Food food, Pawn vehicle)
        {
            if (food.CurCategory < HungerCategory.Hungry)
            {
                return;
            }
            Thing thing;
            Pawn  pawn2;

            if (VirtualPlantsUtility.CanEatVirtualPlantsNow(pawn))
            {
                VirtualPlantsUtility.EatVirtualPlants(pawn);
            }
            else if (CompVehicleUtility.TryGetBestFood(vehicle, pawn, out thing, out pawn2))
            {
                food.CurLevel += thing.Ingested(pawn, food.NutritionWanted);
                if (thing.Destroyed)
                {
                    if (pawn2 != null)
                    {
                        vehicle.inventory.innerContainer.Remove(thing);
                        //caravan.RecacheImmobilizedNow();
                        //caravan.RecacheDaysWorthOfFood();
                    }
                    //if (!CompVehicleUtility.TryGetBestFood(vehicle, pawn, out thing, out pawn2))
                    //{
                    //    Messages.Message("MessageCaravanRunOutOfFood".Translate(new object[]
                    //    {
                    //caravan.LabelCap,
                    //pawn.Label
                    //    }), caravan, MessageSound.SeriousAlert);
                    //}
                }
            }
        }
 private static void TrySatisfyFoodNeed(Pawn pawn, Need_Food food, Caravan caravan)
 {
     if ((int)food.CurCategory >= 1)
     {
         Thing thing = default(Thing);
         Pawn  pawn2 = default(Pawn);
         if (VirtualPlantsUtility.CanEatVirtualPlantsNow(pawn))
         {
             VirtualPlantsUtility.EatVirtualPlants(pawn);
         }
         else if (CaravanInventoryUtility.TryGetBestFood(caravan, pawn, out thing, out pawn2))
         {
             food.CurLevel += thing.Ingested(pawn, food.NutritionWanted);
             if (thing.Destroyed)
             {
                 if (pawn2 != null)
                 {
                     pawn2.inventory.innerContainer.Remove(thing);
                     caravan.RecacheImmobilizedNow();
                     caravan.RecacheDaysWorthOfFood();
                 }
                 if (!CaravanInventoryUtility.TryGetBestFood(caravan, pawn, out thing, out pawn2))
                 {
                     Messages.Message("MessageCaravanRunOutOfFood".Translate(caravan.LabelCap, pawn.Label), caravan, MessageTypeDefOf.ThreatBig);
                 }
             }
         }
     }
 }
 private void TrySatisfyFoodNeed(Pawn pawn, Need_Food food)
 {
     if (food.CurLevelPercentage < 0.4f)
     {
         food.CurLevel = food.MaxLevel;
     }
 }
示例#5
0
        // RimWorld.Planet.CaravanPawnsNeedsUtility
        public static void TrySatisfyFoodNeed(Pawn pawn, Need_Food food, Pawn vehicle)
        {
            if (food.CurCategory < HungerCategory.Hungry)
            {
                return;
            }
            Thing thing;
            Pawn  pawn2;

            if (VirtualPlantsUtility.CanEatVirtualPlantsNow(pawn))
            {
                VirtualPlantsUtility.EatVirtualPlants(pawn);
            }
            else if (TryGetBestFood(vehicle, pawn, out thing, out pawn2))
            {
                food.CurLevel += thing.Ingested(pawn, food.NutritionWanted);
                if (thing.Destroyed)
                {
                    if (pawn2 != null)
                    {
                        vehicle.inventory.innerContainer.Remove(thing);
                    }
                }
            }
        }
示例#6
0
        protected override Job TryGiveJob(Pawn pawn)
        {
            if (HiveUtility.JobGivenRecentTick(pawn, "BI_Ingest"))
            {
                return(null);
            }
            Need_Food food = pawn.needs.food;

            if (food == null || food.CurCategory < minCategory)
            {
                return(null);
            }
            Predicate <Thing> validator = (Thing t) => t.def.category == ThingCategory.Item && t.IngestibleNow && t.def.defName == "InsectJelly" && pawn.RaceProps.CanEverEat(t) && pawn.CanReserve(t);
            Thing             thing     = GenClosest.ClosestThingReachable(pawn.Position, pawn.Map, ThingRequest.ForGroup(ThingRequestGroup.HaulableAlways), PathEndMode.OnCell, TraverseParms.For(pawn, Danger.Deadly, TraverseMode.ByPawn, false), 12f, validator, null, 0, -1, false, RegionType.Set_Passable, false);

            if (thing == null)
            {
                return(null);
            }
            float nutrition = FoodUtility.GetNutrition(thing, thing.def);

            return(new Job(DefDatabase <JobDef> .GetNamed("BI_Ingest"), thing)
            {
                count = FoodUtility.WillIngestStackCountOf(pawn, thing.def, nutrition)
            });
        }
示例#7
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;
                    }
                }
            }
        }
示例#8
0
 public override bool ActivateOn(Lord lord, TriggerSignal signal)
 {
     if (signal.type == TriggerSignalType.Tick)
     {
         for (int i = 0; i < lord.ownedPawns.Count; i++)
         {
             if (GenAI.EnemyIsNear(lord.ownedPawns[i], 10f))
             {
                 return(false);
             }
             Need_Rest rest = lord.ownedPawns[i].needs.rest;
             if (rest != null)
             {
                 if (rest.CurLevelPercentage < 0.14f + this.extraRestThreshOffset && !lord.ownedPawns[i].Awake())
                 {
                     return(true);
                 }
             }
             Need_Food food = lord.ownedPawns[i].needs.food;
             if (food != null)
             {
                 if (food.CurCategory == HungerCategory.Starving)
                 {
                     return(true);
                 }
             }
         }
         return(false);
     }
     return(false);
 }
示例#9
0
 public static void SCP939_Starving(Need_Food __instance, Pawn ___pawn)
 {
     if (___pawn.def.defName == "SCP939_A")
     {
         __instance.CurLevel = 0.1f;
     }
 }
示例#10
0
        public override float GetPriority(Pawn pawn)
        {
            Need_Food food = pawn.needs.food;

            if (food == null)
            {
                return(0f);
            }
            if (pawn.needs.food.CurCategory < HungerCategory.Starving && FoodUtility.ShouldBeFedBySomeone(pawn))
            {
                return(0f);
            }
            if (food.CurCategory < this.minCategory)
            {
                return(0f);
            }
            if (food.CurLevelPercentage > this.maxLevelPercentage)
            {
                return(0f);
            }
            if (food.CurLevelPercentage < pawn.RaceProps.FoodLevelPercentageWantEat)
            {
                return(9.5f);
            }
            return(0f);
        }
示例#11
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;
                 }
             }
         }
     }
 }
 private static void TrySatisfyPawnNeeds(Pawn pawn, Caravan caravan)
 {
     if (!pawn.Dead)
     {
         List <Need> allNeeds = pawn.needs.AllNeeds;
         for (int i = 0; i < allNeeds.Count; i++)
         {
             Need          need          = allNeeds[i];
             Need_Rest     need_Rest     = need as Need_Rest;
             Need_Food     need_Food     = need as Need_Food;
             Need_Chemical need_Chemical = need as Need_Chemical;
             if (need_Rest != null)
             {
                 CaravanPawnsNeedsUtility.TrySatisfyRestNeed(pawn, need_Rest, caravan);
             }
             else if (need_Food != null)
             {
                 CaravanPawnsNeedsUtility.TrySatisfyFoodNeed(pawn, need_Food, caravan);
             }
             else if (need_Chemical != null)
             {
                 CaravanPawnsNeedsUtility.TrySatisfyChemicalNeed(pawn, need_Chemical, caravan);
             }
         }
     }
 }
示例#13
0
        protected override void Impact(Thing hitThing)
        {
            base.Impact(hitThing);

            if (def != null && hitThing != null && hitThing is Pawn hitPawn)
            {
                var rand = Rand.Value;
                var hungerTriggerChance = HungerGuns_Settings.percentChanceToTriggerHunger;
                if (rand <= hungerTriggerChance && !hitPawn.health.hediffSet.HasHediff(HediffDefOf.Malnutrition))
                {
                    Messages.Message("Bullet_HungerBullet_SuccessMessage".Translate(
                                         this.launcher.Label
                                         ), MessageTypeDefOf.NeutralEvent);

                    Need_Food foodNeed = hitPawn.needs.food;
                    foodNeed.CurLevelPercentage = 0;
                    foodNeed.CurLevel           = 0;
                    hitPawn.needs.food          = foodNeed;
                    hitPawn?.health?.AddHediff(HediffDefOf.Malnutrition);

                    hitPawn?.mindState?.priorityWork?.ClearPrioritizedWorkAndJobQueue();
                    hitPawn?.mindState?.mentalStateHandler?.TryStartMentalState(DefDatabase <MentalStateDef> .GetNamed("Binging_Food"));
                }
                else
                {
                    MoteMaker.ThrowText(hitThing.PositionHeld.ToVector3(), hitThing.MapHeld, "Bullet_HungerBullet_FailureMote".Translate((int)hungerTriggerChance), 12f);
                }
            }
        }
        // Token: 0x0600005B RID: 91 RVA: 0x00004948 File Offset: 0x00002B48
        public static void Patch_Need_Food_Starving_Get(ref Need_Food __instance, ref bool __result)
        {
            Pawn pawn = HarmonyPatches.Need_Food_Starving_GetPawn(__instance);
            bool flag = pawn != null && pawn.def == ThingDefOf.ChjAndroid;

            if (flag)
            {
                __result = false;
            }
        }
示例#15
0
        protected override Job TryGiveJob(Pawn pawn)
        {
            Need_Food food = pawn.needs.food;

            if (food == null || food.CurCategory < this.minCategory || food.CurLevelPercentage > this.maxLevelPercentage)
            {
                return(null);
            }
            Thing thing = null;

            if (!FerroFoods.Foods.NullOrEmpty())
            {
                foreach (var item in FerroFoods.Foods)
                {
                    thing = FindFerroFood(item, pawn);

                    if (thing != null)
                    {
                        break;
                    }
                }
            }
            else
            {
                return(null);
            }
            if (thing != null && pawn.Map.reservationManager.CanReserve(pawn, thing, 1))
            {
                // you need to set the jobdef here
                Job job3 = JobMaker.MakeJob(DefDatabase <JobDef> .GetNamed("JOBDEF", true), thing);
                job3.count = 1;// FoodUtility.WillIngestStackCountOf(pawn, thingDef, nutrition);
                return(job3);
            }
            else
            {
                if (pawn.Map != null && pawn.needs.food.CurLevelPercentage < pawn.needs.food.PercentageThreshHungry && pawn.Awake())
                {
                    ThingDef newThing  = FerroFoods.Foods.RandomElement();
                    Thing    newcorpse = null;
                    int      count     = Rand.Range(1, 10);
                    for (int i = 0; i < count; i++)
                    {
                        newcorpse = GenSpawn.Spawn(newThing, pawn.Position, pawn.Map, WipeMode.Vanish);
                    }

                    if (this.effecter == null)
                    {
                        this.effecter = EffecterDefOf.Mine.Spawn();
                    }
                    this.effecter.Trigger(pawn, newcorpse);
                }
            }
            return(null);
        }
示例#16
0
        static bool Prefix(ref ThoughtState __result, Pawn p)
        {
            if (p.needs.food == null)
            {
                __result = ThoughtState.Inactive;
                return(false);
            }
            if (p.RaceProps.Humanlike && p.timetable != null)
            {
                TimeAssignmentDef timeAssignmentDef = p.timetable.CurrentAssignment;
                if (timeAssignmentDef != TimeAssignmentDefDinner.DinnerDef)
                {
                    Need_Food food = p.needs.food;
                    if (p.timetable.GetAssignment((GenLocalDate.HourOfDay(p) + 1) % 24) == TimeAssignmentDefDinner.DinnerDef &&
                        food.CurLevelPercentage > p.RaceProps.FoodLevelPercentageWantEat * 0.45f && food.CurCategory >= HungerCategory.Hungry)
                    {//下一小时是dinner时间并且饥饿度百分比>0.45并且处于饥饿及以上类型状态
                        __result = ThoughtState.ActiveAtStage(7);
                        return(false);
                    }
                }
            }
            switch (p.needs.food.CurCategory)
            {
            case HungerCategory.Fed:
                __result = ThoughtState.Inactive;
                return(false);

            case HungerCategory.Hungry:
                __result = ThoughtState.ActiveAtStage(0);
                return(false);

            case HungerCategory.UrgentlyHungry:
                __result = ThoughtState.ActiveAtStage(1);
                return(false);

            case HungerCategory.Starving:
            {
                Hediff firstHediffOfDef = p.health.hediffSet.GetFirstHediffOfDef(HediffDefOf.Malnutrition, false);
                int    num = (firstHediffOfDef == null) ? 0 : firstHediffOfDef.CurStageIndex;
                if (num > 4)
                {
                    num = 4;
                }
                __result = ThoughtState.ActiveAtStage(2 + num);
                return(false);
            }

            default:
                throw new NotImplementedException();
            }
        }
示例#17
0
        private static bool MaxLevel_Pre(Need_Food __instance, ref float __result)
        {
            var pawn = __instance.pawn;

            if (pawn == null)
            {
                return(true);
            }

            int curLifeStageIdx = pawn.ageTracker.CurLifeStageIndex;
            var lifeStageAges   = pawn.RaceProps.lifeStageAges;

            if (curLifeStageIdx >= lifeStageAges.Count)
            {
                return(true);
            }

            var curLifeStage = lifeStageAges[curLifeStageIdx].def;

            // pawn.ageTracker.CurLifeStage.foodMaxFactor;
            float foodMaxFactor = curLifeStage.foodMaxFactor;

            // pawn.BodySize * foodMaxFactor
            __result = curLifeStage.bodySizeFactor * pawn.RaceProps.baseBodySize * foodMaxFactor;
            if (pawn.ageTracker.AgeBiologicalYears >= 13)
            {
                if (__result < 0.85f)
                {
                    __result = 0.85f;
                }
            }
            else if (__result < 0.6f)
            {
                __result = 0.6f;
            }
            return(false);

            /*
             * public int CurLifeStageIndex {
             *              if (this.cachedLifeStageIndex < 0)
             *                      this.RecalculateLifeStageIndex();
             *                  return this.cachedLifeStageIndex;
             *      }
             *      public LifeStageDef CurLifeStage => this.CurLifeStageRace.def;
             *      public LifeStageAge CurLifeStageRace => this.pawn.RaceProps.lifeStageAges[this.CurLifeStageIndex];
             * public float BodySize => this.ageTracker.CurLifeStage.bodySizeFactor * this.RaceProps.baseBodySize;
             */
        }
示例#18
0
        public void TryFeed()
        {
            Need_Food need = pawn.needs.TryGetNeed <Need_Food>();

            if (need == null)
            {
                return;
            }

            if (need.CurLevel < 0.10f)
            {
                //Log.Message("Cocoon::TryFeed() " + xxx.get_pawnname(pawn) + " need to be fed");
                float nutrition_amount = need.MaxLevel / 5f;
                pawn.needs.food.CurLevel += nutrition_amount;
            }
        }
示例#19
0
        public void IngestDrug(Pawn pawn, Thing drug, Pawn drugOwner)
        {
            float     num  = drug.Ingested(pawn, 0f);
            Need_Food food = pawn.needs.food;

            if (food != null)
            {
                food.CurLevel += num;
            }
            if (drug.Destroyed && drugOwner != null)
            {
                drugOwner.inventory.innerContainer.Remove(drug);
                caravan.RecacheImmobilizedNow();
                caravan.RecacheDaysWorthOfFood();
            }
        }
示例#20
0
        public override void CompTick()
        {
            /*
             * if (parent.Faction == null)
             * {
             *  parent.SetFaction(Find.FactionManager.FirstFactionOfDef(XenomorphDefOf.RRY_Xenomorph));
             * }
             */
            base.CompTick();
            this.ticksSinceHeal++;
            bool flag = this.ticksSinceHeal > this.healIntervalTicks;

            if (flag)
            {
                bool flag2 = pawn.health.hediffSet.HasNaturallyHealingInjury();
                if (flag2)
                {
                    this.ticksSinceHeal = 0;
                    float num = 10f;
                    num = num * pawn.HealthScale * 0.01f;
                    Need_Food food = pawn.needs.food;
                    if (food.CurLevel > (num / 100))
                    {
                        Hediff_Injury hediff_Injury = GenCollection.RandomElement <Hediff_Injury>
                                                          (from x in pawn.health.hediffSet.GetHediffs <Hediff_Injury>()
                                                          where HediffUtility.CanHealNaturally(x)
                                                          select x);
                        doClot(pawn);
                        if (hediff_Injury != null)
                        {
                            hediff_Injury.Heal(num);
                            food.CurLevel -= (num / 100);
                            string text     = string.Format("{0} healed {1} for {2} and food reduced to {3}", pawn.LabelCap, hediff_Injury.Label, num, food.CurLevel);
                            bool   selected = Find.Selector.SingleSelectedThing == pawn;
                            if (selected && Prefs.DevMode)
                            {
                                //    Log.Message(text);
                            }
                        }
                    }
                }
            }
        }
示例#21
0
        public void SatisfyHunger()
        {
            Need_Food need = pawn.needs.TryGetNeed <Need_Food>();

            if (need == null)
            {
                return;
            }
            //pawn.PositionHeld.IsInPrisonCell(pawn.Map)
            //Log.Message("Cocoon::SatisfyHunger() " + xxx.get_pawnname(pawn) + " IsInPrisonCell " + pawn.PositionHeld.IsInPrisonCell(pawn.Map));
            //Log.Message("Cocoon::SatisfyHunger() " + xxx.get_pawnname(pawn) + " GetRoom " + pawn.PositionHeld.GetRoom(pawn.Map));
            //Log.Message("Cocoon::SatisfyHunger() " + xxx.get_pawnname(pawn) + " GetRoom " + pawn.PositionHeld.GetZone(pawn.Map));

            if (need.CurLevel < 0.15f)
            {
                //Log.Message("Cocoon::SatisfyHunger() " + xxx.get_pawnname(pawn) + " need to eat");
                float nutrition_amount = need.MaxLevel / 5f;
                pawn.needs.food.CurLevel += nutrition_amount;
            }
        }
        private void TrySatisfyPawnNeeds(Pawn pawn)
        {
            if (pawn.Dead)
            {
                return;
            }
            List <Need> allNeeds = pawn.needs.AllNeeds;

            for (int i = 0; i < allNeeds.Count; i++)
            {
                Need          need          = allNeeds[i];
                Need_Rest     need_Rest     = need as Need_Rest;
                Need_Food     need_Food     = need as Need_Food;
                Need_Chemical need_Chemical = need as Need_Chemical;
                Need_Joy      need_Joy      = need as Need_Joy;
                if (need_Rest != null)
                {
                    TrySatisfyRestNeed(pawn, need_Rest);
                }
                else if (need_Food != null)
                {
                    TrySatisfyFoodNeed(pawn, need_Food);
                }
                else if (need_Chemical != null)
                {
                    TrySatisfyChemicalNeed(pawn, need_Chemical);
                }
                else if (need_Joy != null)
                {
                    TrySatisfyJoyNeed(pawn, need_Joy);
                }
            }
            Pawn_PsychicEntropyTracker psychicEntropy = pawn.psychicEntropy;

            if (psychicEntropy.Psylink != null)
            {
                TryGainPsyfocus(psychicEntropy);
            }
        }
        protected override Job TryGiveJob(Pawn pawn)
        {
            FoodUtility_Patch.forWendigo = true;
            Need_Food food = pawn.needs.food;

            if (food == null || (int)food.CurCategory < (int)minCategory || food.CurLevelPercentage > maxLevelPercentage)
            {
                FoodUtility_Patch.forWendigo = false;
                return(null);
            }
            bool allowCorpse = true;
            bool desperate   = pawn.needs.food.CurCategory == HungerCategory.Starving;

            if (!FoodUtility.TryFindBestFoodSourceFor(pawn, pawn, desperate, out var foodSource, out var foodDef, canRefillDispenser: true, canUseInventory: true, allowForbidden: false, allowCorpse, allowSociallyImproper: false, pawn.IsWildMan(), forceScanWholeMap))
            {
                FoodUtility_Patch.forWendigo = false;
                return(null);
            }
            Pawn pawn2 = foodSource as Pawn;

            if (pawn2 != null)
            {
                Job job = JobMaker.MakeJob(JobDefOf.PredatorHunt, pawn2);
                job.killIncappedTarget       = true;
                FoodUtility_Patch.forWendigo = false;
                return(job);
            }

            FoodUtility_Patch.forWendigo = true;
            float nutrition = FoodUtility.GetNutrition(foodSource, foodDef);
            Job   job3      = JobMaker.MakeJob(WendigoDefOf.RCW_Ingest, foodSource);

            job3.count = FoodUtility.WillIngestStackCountOf(pawn, foodDef, nutrition);
            FoodUtility_Patch.forWendigo = false;
            return(job3);
        }
        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);
        }
 // Token: 0x06000054 RID: 84 RVA: 0x000045C8 File Offset: 0x000027C8
 public static Pawn Need_Food_Starving_GetPawn(Need_Food instance)
 {
     return((Pawn)HarmonyPatches.int_Need_Food_Starving_GetPawn.GetValue(instance));
 }
示例#26
0
        protected override Job TryGiveJob(Pawn pawn)
        {
            Need_Food food = pawn.needs.food;

            if (food == null || food.CurCategory < this.minCategory || food.CurLevelPercentage > this.maxLevelPercentage)
            {
                return(null);
            }

            //Log.Message("Eating");

            ThingDef thingDef = null;
            Thing    thing    = null;

            CompEatWeirdFood comp = pawn.TryGetComp <CompEatWeirdFood>();

            if (comp != null)
            {
                foreach (string customThingToEat in comp.Props.customThingToEat)
                {
                    thingDef = DefDatabase <ThingDef> .GetNamedSilentFail(customThingToEat);

                    if (thingDef != null)
                    {
                        thing = FindWeirdFoodInMap(thingDef, pawn);

                        if (thing != null)
                        {
                            break;
                        }
                    }
                }
            }
            else
            {
                return(null);
            }
            if (thing != null)
            {
                //float nutrition = 1f;
                Job job3 = JobMaker.MakeJob(DefDatabase <JobDef> .GetNamed("AA_IngestWeird", true), thing);
                job3.count = 1;// FoodUtility.WillIngestStackCountOf(pawn, thingDef, nutrition);
                return(job3);
            }
            else
            {
                if ((pawn.Map != null) && comp.Props.digThingIfMapEmpty && (pawn.needs.food.CurLevelPercentage < pawn.needs.food.PercentageThreshHungry) && (pawn.Awake()))
                {
                    ThingDef newThing  = ThingDef.Named(comp.Props.thingToDigIfMapEmpty);
                    Thing    newcorpse = null;
                    for (int i = 0; i < comp.Props.customAmountToDig; i++)
                    {
                        newcorpse = GenSpawn.Spawn(newThing, pawn.Position, pawn.Map, WipeMode.Vanish);
                    }

                    if (this.effecter == null)
                    {
                        this.effecter = EffecterDefOf.Mine.Spawn();
                    }
                    this.effecter.Trigger(pawn, newcorpse);
                }
            }
            return(null);
        }
示例#27
0
        public static void calculateAndApplySemen(Pawn pawn, Pawn partner, xxx.rjwSextype sextype)
        {
            if (!RJWSettings.cum_on_body)
            {
                return;
            }

            Pawn giver, receiver;

            //Rand.PopState();
            //Rand.PushState(RJW_Multiplayer.PredictableSeed());

            //dispenser of the seed
            if (Genital_Helper.has_penis(pawn) || xxx.is_mechanoid(pawn) || xxx.is_insect(pawn))
            {
                giver    = pawn;
                receiver = partner;
            }
            else if (partner != null && (Genital_Helper.has_penis(partner) || xxx.is_mechanoid(partner) || xxx.is_insect(partner)))
            {
                giver    = partner;
                receiver = pawn;
            }
            else            //female on female or genderless - no s***n dispensed; maybe add futa support?
            {
                return;
            }

            //slimes do not waste fluids?
            //if (xxx.is_slime(giver)) return;

            //determine entity:
            int entityType = SemenHelper.CUM_NORMAL;

            if (xxx.is_mechanoid(giver))
            {
                entityType = SemenHelper.CUM_MECHA;
            }
            else if (xxx.is_insect(giver))
            {
                entityType = SemenHelper.CUM_INSECT;
            }

            //get pawn genitalia:
            BodyPartRecord genitals;

            if (xxx.is_mechanoid(giver))
            {
                genitals = giver.RaceProps.body.AllParts.Find(x => string.Equals(x.def.defName, "MechGenitals"));
            }
            else            //insects, animals, humans
            {
                genitals = giver.RaceProps.body.AllParts.Find(x => x.def == SemenHelper.genitalsDef);
            }
            //no cum without genitals
            if (genitals == null)
            {
                return;
            }

            //calculate s***n amount:
            Need  sexNeed   = giver.needs.AllNeeds.Find(x => string.Equals(x.def.defName, "Sex"));
            float horniness = 1f;

            if (sexNeed != null)            //non-humans don't have it - therefore just use the default value
            {
                horniness = 1f - sexNeed.CurLevel;
            }

            float ageScale  = Math.Min(80 / SexUtility.ScaleToHumanAge(giver), 1.0f);           //calculation lifted from rjw
            float cumAmount = horniness * giver.BodySize * ageScale * RJWSettings.cum_on_body_amount_adjust;

            ;

            if (xxx.has_quirk(giver, "Messy"))
            {
                cumAmount *= 1.5f;
            }

            //if no partner -> masturbation, apply some cum on self:
            //if (partner == null && sextype == xxx.rjwSextype.Autofellatio)
            //{
            //	if (!xxx.is_slime(giver))
            //		SemenHelper.cumOn(giver, BodyPartDefOf.Jaw, cumAmount, giver);
            //	return;
            //}
            if (partner == null && sextype == xxx.rjwSextype.Masturbation)
            {
                if (!xxx.is_slime(giver))
                {
                    SemenHelper.cumOn(giver, genitals, cumAmount * 0.3f, giver);                    //pawns are usually not super-messy -> only apply 30%
                }
                return;
            }
            else if (partner != null)
            {
                List <BodyPartRecord>        targetParts    = new List <BodyPartRecord>(); //which to apply s***n on
                IEnumerable <BodyPartRecord> availableParts = SemenHelper.getAvailableBodyParts(receiver);
                BodyPartRecord randomPart;                                                 //not always needed

                switch (sextype)
                {
                case rjw.xxx.rjwSextype.Anal:
                    targetParts.Add(receiver.RaceProps.body.AllParts.Find(x => x.def == SemenHelper.anusDef));
                    break;

                case rjw.xxx.rjwSextype.Boobjob:
                    targetParts.Add(receiver.RaceProps.body.AllParts.Find(x => x.def == SemenHelper.chestDef));
                    break;

                case rjw.xxx.rjwSextype.DoublePenetration:
                    targetParts.Add(receiver.RaceProps.body.AllParts.Find(x => x.def == SemenHelper.anusDef));
                    targetParts.Add(receiver.RaceProps.body.AllParts.Find(x => x.def == SemenHelper.genitalsDef));
                    break;

                case rjw.xxx.rjwSextype.Fingering:
                    cumAmount = 0;
                    break;

                case rjw.xxx.rjwSextype.Fisting:
                    cumAmount = 0;
                    break;

                case rjw.xxx.rjwSextype.Footjob:
                    //random part:
                    availableParts.TryRandomElement <BodyPartRecord>(out randomPart);
                    targetParts.Add(randomPart);
                    break;

                case rjw.xxx.rjwSextype.Handjob:
                    //random part:
                    availableParts.TryRandomElement <BodyPartRecord>(out randomPart);
                    targetParts.Add(randomPart);
                    break;

                case rjw.xxx.rjwSextype.Masturbation:
                    cumAmount *= 2f;
                    break;

                case rjw.xxx.rjwSextype.MechImplant:
                    //one of the openings:
                    int random = Rand.Range(0, 3);
                    if (random == 0)
                    {
                        targetParts.Add(receiver.RaceProps.body.AllParts.Find(x => x.def == SemenHelper.genitalsDef));
                    }
                    else if (random == 1)
                    {
                        targetParts.Add(receiver.RaceProps.body.AllParts.Find(x => x.def == SemenHelper.anusDef));
                    }
                    else if (random == 2)
                    {
                        targetParts.Add(receiver.RaceProps.body.AllParts.Find(x => x.def == BodyPartDefOf.Jaw));
                    }
                    break;

                case rjw.xxx.rjwSextype.MutualMasturbation:
                    //random
                    availableParts.TryRandomElement <BodyPartRecord>(out randomPart);
                    targetParts.Add(randomPart);
                    break;

                case rjw.xxx.rjwSextype.None:
                    cumAmount = 0;
                    break;

                case rjw.xxx.rjwSextype.Oral:
                    targetParts.Add(receiver.RaceProps.body.AllParts.Find(x => x.def == BodyPartDefOf.Jaw));
                    break;

                case rjw.xxx.rjwSextype.Scissoring:
                    //I guess if it came to here, a male must be involved?
                    targetParts.Add(receiver.RaceProps.body.AllParts.Find(x => x.def == SemenHelper.genitalsDef));
                    break;

                case rjw.xxx.rjwSextype.Vaginal:
                    targetParts.Add(receiver.RaceProps.body.AllParts.Find(x => x.def == SemenHelper.genitalsDef));
                    break;
                }

                if (cumAmount > 0)
                {
                    if (xxx.is_slime(receiver))
                    {
                        //slime absorb cum
                        //this needs balancing, since cumamount ranges 0-10(?) which is fine for cum/hentai but not very realistic for feeding
                        //using TransferNutrition for now
                        //Log.Message("cumAmount " + cumAmount);
                        //float nutrition_amount = cumAmount/10;

                        Need_Food need = need = giver.needs.TryGetNeed <Need_Food>();
                        if (need == null)
                        {
                            //Log.Message("xxx::TransferNutrition() " + xxx.get_pawnname(pawn) + " doesn't track nutrition in itself, probably shouldn't feed the others");
                            return;
                        }

                        if (receiver?.needs?.TryGetNeed <Need_Food>() != null)
                        {
                            //Log.Message("xxx::TransferNutrition() " +  xxx.get_pawnname(partner) + " can receive");
                            float nutrition_amount = Math.Min(need.MaxLevel / 15f, need.CurLevel);                             //body size is taken into account implicitly by need.MaxLevel
                            receiver.needs.food.CurLevel += nutrition_amount;
                        }
                    }
                    else
                    {
                        SemenHelper.cumOn(giver, genitals, cumAmount * 0.3f, giver, entityType);                        //cum on self - smaller amount
                        foreach (BodyPartRecord bpr in targetParts)
                        {
                            if (bpr != null)
                            {
                                SemenHelper.cumOn(receiver, bpr, cumAmount, giver, entityType);                                //cum on partner
                            }
                        }
                    }
                }
            }
        }
        static bool Prefix(HungerCategory ___minCategory, float ___maxLevelPercentage, ref float __result, Pawn pawn)
        {
            //Log.Message("1");
            Need_Food food = pawn.needs.food;

            if (food == null)
            {
                __result = 0f; return(false);
            }
            //Log.Message("2");
            if (pawn.needs.food.CurCategory < HungerCategory.Starving && FoodUtility.ShouldBeFedBySomeone(pawn))
            {
                __result = 0f; return(false);
            }
            //Log.Message("3");
            if (food.CurCategory < ___minCategory)
            {
                __result = 0f; return(false);
            }
            //Log.Message("4");
            if (food.CurLevelPercentage > ___maxLevelPercentage)
            {
                __result = 0f; return(false);
            }
            //Log.Message("5");
            if (pawn.RaceProps.Humanlike)
            {
                if (food.CurLevelPercentage < pawn.RaceProps.FoodLevelPercentageWantEat + ModSetting.eatThreshold)
                {
                    if (pawn.timetable == null)
                    {
                        if (food.CurLevelPercentage < pawn.RaceProps.FoodLevelPercentageWantEat)
                        {
                            __result = 9.5f;
                        }
                        else
                        {
                            __result = 0f;
                        }
                        return(false);
                    }
                    //Log.Message("6");
                    TimeAssignmentDef timeAssignmentDef = (pawn.timetable == null) ? TimeAssignmentDefOf.Anything : pawn.timetable.CurrentAssignment;
                    if (timeAssignmentDef != TimeAssignmentDefDinner.DinnerDef)
                    {
                        //Log.Message("7");
                        if (pawn.timetable.GetAssignment((GenLocalDate.HourOfDay(pawn) + 1) % 24) == TimeAssignmentDefDinner.DinnerDef && food.CurLevelPercentage > pawn.RaceProps.FoodLevelPercentageWantEat * 0.48f)
                        {//下一小时是dinner时间并且饥饿度百分比>0.45就不吃饭
                            __result = 0f;
                            return(false);
                        }
                        if (pawn.timetable.GetAssignment((GenLocalDate.HourOfDay(pawn) + 2) % 24) == TimeAssignmentDefDinner.DinnerDef && food.CurLevelPercentage > pawn.RaceProps.FoodLevelPercentageWantEat * 0.8f)
                        {//下2小时是dinner时间并且饥饿度百分比>0.8就不吃饭
                            __result = 0f;
                            return(false);
                        }
                        //Log.Message("8");
                        if (food.CurLevelPercentage < pawn.RaceProps.FoodLevelPercentageWantEat)
                        {
                            __result = 9.5f;
                        }
                        else
                        {
                            __result = 0f;
                        }
                        return(false);
                    }
                    if (food.CurLevelPercentage < pawn.RaceProps.FoodLevelPercentageWantEat)
                    {
                        __result = 9.5f;
                    }
                    else
                    {
                        __result = 7.25f;
                    }
                    return(false);
                }
                else
                {
                    __result = 0;
                }
                //Log.Message("{0} food priority = {1}".Translate(pawn.Label, __result));
            }
            else if (food.CurLevelPercentage < pawn.RaceProps.FoodLevelPercentageWantEat)
            {
                __result = 9.5f;
            }
            else
            {
                __result = 0f;
            }
            return(false);
        }
示例#29
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);
        }