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); } } }
// 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; } }
// 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); } } } }
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) }); }
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; } } } }
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); }
public static void SCP939_Starving(Need_Food __instance, Pawn ___pawn) { if (___pawn.def.defName == "SCP939_A") { __instance.CurLevel = 0.1f; } }
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); }
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); } } } }
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; } }
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); }
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(); } }
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; */ }
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; } }
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(); } }
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); } } } } } }
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)); }
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); }
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); }
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); }