protected override void IngestedCalculateAmounts(Pawn ingester, float nutritionWanted, out int numTaken, out float nutritionIngested) { BodyPartRecord bodyPartRecord = this.GetBestBodyPartToEat(ingester, nutritionWanted); if (bodyPartRecord == null) { Log.Error(ingester + " ate " + this + " but no body part was found. Replacing with core part."); bodyPartRecord = this.InnerPawn.RaceProps.body.corePart; } float bodyPartNutrition = FoodUtility.GetBodyPartNutrition(this.InnerPawn, bodyPartRecord); if (bodyPartRecord == this.InnerPawn.RaceProps.body.corePart) { if (PawnUtility.ShouldSendNotificationAbout(this.InnerPawn) && this.InnerPawn.RaceProps.Humanlike) { Messages.Message("MessageEatenByPredator".Translate(this.InnerPawn.LabelShort, ingester.LabelIndefinite()).CapitalizeFirst(), ingester, MessageTypeDefOf.NegativeEvent); } numTaken = 1; } else { Hediff_MissingPart hediff_MissingPart = (Hediff_MissingPart)HediffMaker.MakeHediff(HediffDefOf.MissingBodyPart, this.InnerPawn, bodyPartRecord); hediff_MissingPart.lastInjury = HediffDefOf.Bite; hediff_MissingPart.IsFresh = true; this.InnerPawn.health.AddHediff(hediff_MissingPart, null, null); numTaken = 0; } if (ingester.RaceProps.Humanlike && Rand.Value < 0.05000000074505806) { FoodUtility.AddFoodPoisoningHediff(ingester, this); } nutritionIngested = bodyPartNutrition; }
// Token: 0x060029AF RID: 10671 RVA: 0x0013C0B7 File Offset: 0x0013A4B7 public override void PostIngested(Pawn ingester) { if (this.Stage != RotStage.Fresh) { FoodUtility.AddFoodPoisoningHediff(ingester, this.parent, FoodPoisonCause.Rotten); } }
public override void PostIngested(Pawn ingester) { if (this.Stage != RotStage.Fresh && FoodUtility.GetFoodPoisonChanceFactor(ingester) > 1.401298E-45f) { FoodUtility.AddFoodPoisoningHediff(ingester, this.parent, FoodPoisonCause.Rotten); } }
public float Ingested(Pawn ingester, float nutritionWanted) { if (Destroyed) { Log.Error(ingester + " ingested destroyed thing " + this); return(0f); } if (!IngestibleNow) { Log.Error(ingester + " ingested IngestibleNow=false thing " + this); return(0f); } ingester.mindState.lastIngestTick = Find.TickManager.TicksGame; if (def.ingestible.outcomeDoers != null) { for (int i = 0; i < def.ingestible.outcomeDoers.Count; i++) { def.ingestible.outcomeDoers[i].DoIngestionOutcome(ingester, this); } } if (ingester.needs.mood != null) { List <ThoughtDef> list = FoodUtility.ThoughtsFromIngesting(ingester, this, def); for (int j = 0; j < list.Count; j++) { ingester.needs.mood.thoughts.memories.TryGainMemory(list[j]); } } if (ingester.IsColonist && FoodUtility.IsHumanlikeMeatOrHumanlikeCorpse(this)) { TaleRecorder.RecordTale(TaleDefOf.AteRawHumanlikeMeat, ingester); } IngestedCalculateAmounts(ingester, nutritionWanted, out int numTaken, out float nutritionIngested); if (!ingester.Dead && ingester.needs.joy != null && Mathf.Abs(def.ingestible.joy) > 0.0001f && numTaken > 0) { JoyKindDef joyKind = (def.ingestible.joyKind == null) ? JoyKindDefOf.Gluttonous : def.ingestible.joyKind; ingester.needs.joy.GainJoy((float)numTaken * def.ingestible.joy, joyKind); } if (ingester.RaceProps.Humanlike && Rand.Chance(this.GetStatValue(StatDefOf.FoodPoisonChanceFixedHuman) * Find.Storyteller.difficulty.foodPoisonChanceFactor)) { FoodUtility.AddFoodPoisoningHediff(ingester, this, FoodPoisonCause.DangerousFoodType); } if (numTaken > 0) { if (numTaken == stackCount) { Destroy(); } else { SplitOff(numTaken); } } PostIngested(ingester); return(nutritionIngested); }
// Token: 0x06000002 RID: 2 RVA: 0x00002058 File Offset: 0x00000258 public override void PostIngested(Pawn ingester) { HediffSet MShedSet = ingester.health.hediffSet; if (MShedSet != null) { if ((MShedSet?.GetFirstHediffOfDef(HediffDef.Named("MSMultiVitamins_High"), false)) == null && Rand.Chance(this.poisonPct * Find.Storyteller.difficulty.foodPoisonChanceFactor)) { FoodUtility.AddFoodPoisoningHediff(ingester, this.parent, this.cause); return; } } else if (Rand.Chance(this.poisonPct * Find.Storyteller.difficulty.foodPoisonChanceFactor)) { FoodUtility.AddFoodPoisoningHediff(ingester, this.parent, this.cause); } }
public float Ingested(Pawn ingester, float nutritionWanted) { if (Destroyed) { Log.Error(string.Concat(ingester, " ingested destroyed thing ", this)); return(0f); } if (!IngestibleNow) { Log.Error(string.Concat(ingester, " ingested IngestibleNow=false thing ", this)); return(0f); } ingester.mindState.lastIngestTick = Find.TickManager.TicksGame; if (ingester.needs.mood != null) { List <ThoughtDef> list = FoodUtility.ThoughtsFromIngesting(ingester, this, def); for (int i = 0; i < list.Count; i++) { ingester.needs.mood.thoughts.memories.TryGainMemory(list[i]); } } if (ingester.needs.drugsDesire != null) { ingester.needs.drugsDesire.Notify_IngestedDrug(this); } if (ingester.IsColonist && FoodUtility.IsHumanlikeMeatOrHumanlikeCorpse(this)) { TaleRecorder.RecordTale(TaleDefOf.AteRawHumanlikeMeat, ingester); } IngestedCalculateAmounts(ingester, nutritionWanted, out var numTaken, out var nutritionIngested); if (!ingester.Dead && ingester.needs.joy != null && Mathf.Abs(def.ingestible.joy) > 0.0001f && numTaken > 0) { JoyKindDef joyKind = ((def.ingestible.joyKind != null) ? def.ingestible.joyKind : JoyKindDefOf.Gluttonous); ingester.needs.joy.GainJoy((float)numTaken * def.ingestible.joy, joyKind); } if (ingester.RaceProps.Humanlike && Rand.Chance(this.GetStatValue(StatDefOf.FoodPoisonChanceFixedHuman) * FoodUtility.GetFoodPoisonChanceFactor(ingester))) { FoodUtility.AddFoodPoisoningHediff(ingester, this, FoodPoisonCause.DangerousFoodType); } bool flag = false; if (numTaken > 0) { if (stackCount == 0) { Log.Error(string.Concat(this, " stack count is 0.")); } if (numTaken == stackCount) { flag = true; } else { SplitOff(numTaken); } } PrePostIngested(ingester); if (flag) { ingester.carryTracker.innerContainer.Remove(this); } if (def.ingestible.outcomeDoers != null) { for (int j = 0; j < def.ingestible.outcomeDoers.Count; j++) { def.ingestible.outcomeDoers[j].DoIngestionOutcome(ingester, this); } } if (flag) { Destroy(); } PostIngested(ingester); return(nutritionIngested); }
public static Toil DrinkFromBuilding(TargetIndex buildingIndex) { int initialTicks = 1; Toil toil = new Toil(); toil.initAction = delegate { var actor = toil.actor; var thing = actor.CurJob.GetTarget(buildingIndex).Thing; var comp = thing.TryGetComp <CompWaterSource>(); var building = thing as IBuilding_DrinkWater; if (actor.needs == null || actor.needs.water() == null || building == null || comp == null || !comp.IsWaterSource) { actor.jobs.EndCurrentJob(JobCondition.Incompletable); return; } var need_water = actor.needs.water(); var waterTypeDef = MizuDef.Dic_WaterTypeDef[comp.WaterType]; // 向きを変更 actor.rotationTracker.FaceCell(actor.Position); // 作業量 actor.jobs.curDriver.ticksLeftThisToil = (int)(comp.BaseDrinkTicks * need_water.WaterWanted); initialTicks = actor.jobs.curDriver.ticksLeftThisToil; if (actor.needs.mood != null) { // 水分摂取による心情変化 foreach (var thoughtDef in MizuUtility.ThoughtsFromGettingWater(actor, thing)) { actor.needs.mood.thoughts.memories.TryGainMemory(thoughtDef); } } // 指定された健康状態になる if (waterTypeDef.hediffs != null) { foreach (var hediff in waterTypeDef.hediffs) { actor.health.AddHediff(HediffMaker.MakeHediff(hediff, actor)); } } // 確率で食中毒 if (Rand.Value < waterTypeDef.foodPoisonChance) { FoodUtility.AddFoodPoisoningHediff(actor, thing, FoodPoisonCause.Unknown); } }; toil.tickAction = delegate { toil.actor.GainComfortFromCellIfPossible(); var need_water = toil.actor.needs.water(); var thing = toil.actor.CurJob.GetTarget(buildingIndex).Thing; var comp = thing.TryGetComp <CompWaterSource>(); var building = thing as IBuilding_DrinkWater; if (thing == null || comp == null || !comp.IsWaterSource || building == null || building.IsEmpty) { toil.actor.jobs.EndCurrentJob(JobCondition.Incompletable); return; } // 徐々に飲む float riseNeedWater = 1 / (float)comp.BaseDrinkTicks; need_water.CurLevel = Mathf.Min(need_water.CurLevel + riseNeedWater, need_water.MaxLevel); building.DrawWater(riseNeedWater * Need_Water.NeedWaterVolumePerDay); }; toil.WithProgressBar(buildingIndex, delegate { return(1f - (float)toil.actor.jobs.curDriver.ticksLeftThisToil / initialTicks); }, false, -0.5f); toil.defaultCompleteMode = ToilCompleteMode.Delay; toil.FailOn((t) => { Pawn actor = toil.actor; var target = actor.CurJob.GetTarget(buildingIndex); if (target.Thing.def.hasInteractionCell) { // 使用場所があるなら使用場所基準 return(target.Thing.InteractionCell.IsForbidden(actor) || !actor.CanReach(target.Thing.InteractionCell, PathEndMode.OnCell, Danger.Deadly)); } else { // 使用場所がないなら設備の場所基準 return(target.Thing.Position.IsForbidden(actor) || !actor.CanReach(target.Thing.Position, PathEndMode.ClosestTouch, Danger.Deadly)); } }); // エフェクト追加 toil.PlaySustainerOrSound(delegate { return(DefDatabase <SoundDef> .GetNamed("Ingest_Beer")); }); return(toil); }
public static float GetWater(Pawn getter, Thing thing, float waterWanted, bool withIngested) { // 摂取しようとしているものが既に消滅している(エラー) // 食事と同時に水分摂取する場合は既に消滅しているので無視する if (!withIngested && thing.Destroyed) { Log.Error(getter + " drank destroyed thing " + thing); return(0f); } // 現在飲めないはずのものを飲もうとしている(エラー) if (!thing.CanDrinkWaterNow()) { Log.Error(getter + " drank CanDrinkWaterNow()=false thing " + thing); return(0f); } if (getter.needs.mood != null) { // 水分摂取による心情変化 foreach (var thoughtDef in ThoughtsFromGettingWater(getter, thing)) { getter.needs.mood.thoughts.memories.TryGainMemory(thoughtDef); } } // 健康状態の変化 var comp = thing.TryGetComp <CompWaterSource>(); if (comp == null) { Log.Error("comp is null"); return(0.0f); } if (!comp.IsWaterSource && comp.DependIngredients == false) { Log.Error("not watersource"); return(0.0f); } if (comp.SourceType != CompProperties_WaterSource.SourceType.Item) { Log.Error("source type is not item"); return(0.0f); } var waterType = GetWaterType(thing); var waterTypeDef = MizuDef.Dic_WaterTypeDef[waterType]; // 指定された健康状態になる if (waterTypeDef.hediffs != null) { foreach (var hediff in waterTypeDef.hediffs) { getter.health.AddHediff(HediffMaker.MakeHediff(hediff, getter)); } } // 確率で食中毒 var animalFactor = getter.RaceProps.Humanlike ? 1f : 0.1f; // 動物は1/10に抑える if (Rand.Value < waterTypeDef.foodPoisonChance * animalFactor) { FoodUtility.AddFoodPoisoningHediff(getter, thing, FoodPoisonCause.Unknown); } // 摂取個数と摂取水分量の計算 thing.GetWaterCalculateAmounts(waterWanted, withIngested, out var drankWaterItemCount, out var gotWaterAmount); if (withIngested) { // 食事の場合は後で個数を計算するのでここでは1個にする gotWaterAmount = comp.WaterAmount; drankWaterItemCount = 1; } // 食事と同時に水分摂取する場合は既に消滅しているので消滅処理をスキップする if (withIngested || drankWaterItemCount <= 0) { return(gotWaterAmount); } if (drankWaterItemCount == thing.stackCount) { // アイテム消費数とスタック数が同じ // →完全消滅 thing.Destroy(); } else { // スタック数と異なる // →消費した数だけ減らす thing.SplitOff(drankWaterItemCount); } return(gotWaterAmount); }
public static float Ingested(this Thing thing, Pawn ingester, float nutritionWanted, BodyPartRecord targetPart) { if (thing.Destroyed) { Log.Error(ingester + " ingested destroyed thing " + thing); return(0f); } if (!thing.IngestibleNow) { Log.Error(ingester + " ingested IngestibleNow=false thing " + thing); return(0f); } Corpse corpse = thing as Corpse; if (corpse == null) { Log.Error(ingester + " ingested NonCorpse thing " + thing); return(0f); } ingester.mindState.lastIngestTick = Find.TickManager.TicksGame; if (ingester.needs.mood != null) { List <FoodUtility.ThoughtFromIngesting> list = FoodUtility.ThoughtsFromIngesting(ingester, thing, thing.def); for (int i = 0; i < list.Count; i++) { ingester.needs.mood.thoughts.memories.TryGainMemory(list[i].thought, null); } } if (ingester.needs.drugsDesire != null) { ingester.needs.drugsDesire.Notify_IngestedDrug(thing); } if (ingester.IsColonist && FoodUtility.IsHumanlikeCorpseOrHumanlikeMeat(thing, thing.def)) { TaleRecorder.RecordTale(TaleDefOf.AteRawHumanlikeMeat, new object[] { ingester }); } corpse.IngestedCalculateAmounts(ingester, targetPart, out int num, out float result); /* * MethodInfo dynMethod = thing.GetType().GetMethod("IngestedCalculateAmounts", * BindingFlags.NonPublic | BindingFlags.Instance); * object[] parameters = new object[] { ingester, nutritionWanted, null, null }; * dynMethod.Invoke(thing, parameters); * // Log.Message(thing+" eaten by "+ingester+" nutritionWanted: "+ nutritionWanted + " num: " + parameters[2] + " result: " + parameters[3]); * num = (int)parameters[2]; * result = (float)parameters[3]; * // thing.IngestedCalculateAmounts(ingester, nutritionWanted, out num, out result); */ if (!ingester.Dead && ingester.needs.joy != null && Mathf.Abs(thing.def.ingestible.joy) > 0.0001f && num > 0) { JoyKindDef joyKind = (thing.def.ingestible.joyKind != null) ? thing.def.ingestible.joyKind : JoyKindDefOf.Gluttonous; ingester.needs.joy.GainJoy((float)num * thing.def.ingestible.joy, joyKind); } if (ingester.RaceProps.Humanlike && Rand.Chance(thing.GetStatValue(StatDefOf.FoodPoisonChanceFixedHuman, true) * FoodUtility.GetFoodPoisonChanceFactor(ingester))) { FoodUtility.AddFoodPoisoningHediff(ingester, thing, FoodPoisonCause.DangerousFoodType); } bool flag = false; if (num > 0) { if (thing.stackCount == 0) { Log.Error(thing + " stack count is 0."); } if (num == thing.stackCount) { flag = true; } else { thing.SplitOff(num); } } MethodInfo dynMethod2 = thing.GetType().GetMethod("PrePostIngested", BindingFlags.NonPublic | BindingFlags.Instance); dynMethod2.Invoke(thing, new object[] { ingester }); // thing.PrePostIngested(ingester); if (flag) { ingester.carryTracker.innerContainer.Remove(thing); } if (thing.def.ingestible.outcomeDoers != null) { for (int j = 0; j < thing.def.ingestible.outcomeDoers.Count; j++) { thing.def.ingestible.outcomeDoers[j].DoIngestionOutcome(ingester, thing); } } if (flag) { thing.Destroy(DestroyMode.Vanish); } MethodInfo dynMethod3 = thing.GetType().GetMethod("PostIngested", BindingFlags.NonPublic | BindingFlags.Instance); dynMethod3.Invoke(thing, new object[] { ingester }); // thing.PostIngested(ingester); return(result); }