public static Toil LayDown(TargetIndex bedOrRestSpotIndex, bool hasBed, bool lookForOtherJobs, bool canSleep = true, bool gainRestAndHealth = true) { Toil layDown = new Toil(); layDown.initAction = delegate { Pawn actor = layDown.actor; actor.pather.StopDead(); JobDriver curDriver = actor.jobs.curDriver; if (hasBed) { Building_Bed t = (Building_Bed)actor.CurJob.GetTarget(bedOrRestSpotIndex).Thing; if (!t.OccupiedRect().Contains(actor.Position)) { Log.Error("Can't start LayDown toil because pawn is not in the bed. pawn=" + actor); actor.jobs.EndCurrentJob(JobCondition.Errored, true); return; } curDriver.layingDown = LayingDownState.LayingInBed; } else { curDriver.layingDown = LayingDownState.LayingSurface; } curDriver.asleep = false; if (actor.mindState.applyBedThoughtsTick == 0) { actor.mindState.applyBedThoughtsTick = Find.TickManager.TicksGame + Rand.Range(2500, 10000); actor.mindState.applyBedThoughtsOnLeave = false; } if (actor.ownership != null && actor.CurrentBed() != actor.ownership.OwnedBed) { ThoughtUtility.RemovePositiveBedroomThoughts(actor); } }; layDown.tickAction = delegate { Pawn actor = layDown.actor; Job curJob = actor.CurJob; JobDriver curDriver = actor.jobs.curDriver; Building_Bed building_Bed = (Building_Bed)curJob.GetTarget(bedOrRestSpotIndex).Thing; actor.GainComfortFromCellIfPossible(); if (!curDriver.asleep) { if (canSleep && ((actor.needs.rest != null && actor.needs.rest.CurLevel < RestUtility.FallAsleepMaxLevel(actor)) || curJob.forceSleep)) { curDriver.asleep = true; } } else if (!canSleep) { curDriver.asleep = false; } else if ((actor.needs.rest == null || actor.needs.rest.CurLevel >= RestUtility.WakeThreshold(actor)) && !curJob.forceSleep) { curDriver.asleep = false; } if (curDriver.asleep && gainRestAndHealth && actor.needs.rest != null) { float num; if (building_Bed != null && building_Bed.def.statBases.StatListContains(StatDefOf.BedRestEffectiveness)) { num = building_Bed.GetStatValue(StatDefOf.BedRestEffectiveness, true); } else { num = 0.8f; } float num2 = RestUtility.PawnHealthRestEffectivenessFactor(actor); num = 0.7f * num + 0.3f * num * num2; actor.needs.rest.TickResting(num); } if (actor.mindState.applyBedThoughtsTick != 0 && actor.mindState.applyBedThoughtsTick <= Find.TickManager.TicksGame) { Toils_LayDown.ApplyBedThoughts(actor); actor.mindState.applyBedThoughtsTick += 60000; actor.mindState.applyBedThoughtsOnLeave = true; } if (actor.IsHashIntervalTick(100) && !actor.Position.Fogged(actor.Map)) { if (curDriver.asleep) { MoteMaker.ThrowMetaIcon(actor.Position, actor.Map, ThingDefOf.Mote_SleepZ); } if (gainRestAndHealth && actor.health.hediffSet.GetNaturallyHealingInjuredParts().Any <BodyPartRecord>()) { MoteMaker.ThrowMetaIcon(actor.Position, actor.Map, ThingDefOf.Mote_HealingCross); } } if (actor.ownership != null && building_Bed != null && !building_Bed.Medical && !building_Bed.owners.Contains(actor)) { if (actor.Downed) { actor.Position = CellFinder.RandomClosewalkCellNear(actor.Position, actor.Map, 1, null); } actor.jobs.EndCurrentJob(JobCondition.Incompletable, true); return; } if (lookForOtherJobs && actor.IsHashIntervalTick(211)) { actor.jobs.CheckForJobOverride(); return; } }; layDown.defaultCompleteMode = ToilCompleteMode.Never; if (hasBed) { layDown.FailOnBedNoLongerUsable(bedOrRestSpotIndex); } layDown.AddFinishAction(delegate { Pawn actor = layDown.actor; JobDriver curDriver = actor.jobs.curDriver; if (actor.mindState.applyBedThoughtsOnLeave) { Toils_LayDown.ApplyBedThoughts(actor); } curDriver.layingDown = LayingDownState.NotLaying; curDriver.asleep = false; }); return(layDown); }
public override void NeedInterval() { if (!base.IsFrozen) { if (this.Resting) { float num = this.lastRestEffectiveness; float num2 = RestUtility.PawnHealthRestEffectivenessFactor(this.pawn); num = 0.7f * num + 0.3f * num * num2; num *= this.pawn.GetStatValue(StatDefOf.RestRateMultiplier, true); if (num > 0f) { this.CurLevel += 0.00571428565f * num; } } else { this.CurLevel -= this.RestFallPerTick * 150f; } } if (this.CurLevel < 0.0001f) { this.ticksAtZero += 150; } else { this.ticksAtZero = 0; } if (this.ticksAtZero > 1000 && this.pawn.Spawned) { float mtb; if (this.ticksAtZero < 15000) { mtb = 0.25f; } else if (this.ticksAtZero < 30000) { mtb = 0.125f; } else if (this.ticksAtZero < 45000) { mtb = 0.0833333358f; } else { mtb = 0.0625f; } if (Rand.MTBEventOccurs(mtb, 60000f, 150f) && (this.pawn.CurJob == null || this.pawn.CurJob.def != JobDefOf.LayDown)) { this.pawn.jobs.StartJob(new Job(JobDefOf.LayDown, this.pawn.Position), JobCondition.InterruptForced, null, false, true, null, new JobTag?(JobTag.SatisfyingNeeds), false); if (this.pawn.InMentalState) { this.pawn.mindState.mentalStateHandler.CurState.RecoverFromState(); } if (PawnUtility.ShouldSendNotificationAbout(this.pawn)) { Messages.Message("MessageInvoluntarySleep".Translate(new object[] { this.pawn.LabelShort }), this.pawn, MessageTypeDefOf.NegativeEvent, true); } TaleRecorder.RecordTale(TaleDefOf.Exhausted, new object[] { this.pawn }); } } }