static bool Prefix(ref Pawn ___pawn, ref Building_Bed ___intOwnedBed) { UnassignAllBedsIfDead(___pawn); if (!Helpers.ShouldRunForPawn(___pawn)) { return(true); } var isInShuttle = !___pawn.Spawned && ___pawn.SpawnedParentOrMe?.Label?.Contains("shuttle") == true; if (isInShuttle) { ___intOwnedBed = null; ThoughtUtility.RemovePositiveBedroomThoughts(___pawn); return(true); } // NOTE: If the bed is unclaimed (typically deconstructed/replaced) on another map this will cause the pawn // to unclaim the bed on CurrentMap. Since UnclaimBed doesn't specify bed we have to guess, and since it's // called from a bunch of places in vanilla (plus whatever from mods) I'd rather just take the occasional // unwanted unclaim instead of trying to patch everywhere. // Temporarily replace pawns owned bed on their map with the bed owned on the current map ClaimBedOnMapIfExists(___pawn, Find.CurrentMap, ref ___intOwnedBed); return(true); }
public static void UnclaimBeds(Pawn pawn, IEnumerable <Building_Bed> beds, ref Building_Bed ___intOwnedBed) { foreach (var bed in beds) { bed?.CompAssignableToPawn?.ForceRemovePawn(pawn); if (pawn.ownership?.OwnedBed == bed) { ___intOwnedBed = null; ThoughtUtility.RemovePositiveBedroomThoughts(pawn); } } }
private static void ClaimBedOnMapIfExists(Pawn ___pawn, Map map, ref Building_Bed ___intOwnedBed) { var pawnBedsOnMap = Helpers.PawnBedsOnMap(___pawn, map); if (pawnBedsOnMap.Any()) { var bed = pawnBedsOnMap.First(); ___intOwnedBed = bed; if (bed.CompAssignableToPawn != null && !bed.CompAssignableToPawn.AssignedPawnsForReading.Contains(___pawn)) { bed.CompAssignableToPawn.ForceAddPawn(___pawn); } ThoughtUtility.RemovePositiveBedroomThoughts(___pawn); } }
static bool Prefix(Building_Bed newBed, Pawn_Ownership __instance, ref Pawn ___pawn, ref Building_Bed ___intOwnedBed) { if (newBed == null || newBed.Medical || !Helpers.ShouldRunForPawn(___pawn) || (newBed.OwnersForReading != null && newBed.OwnersForReading.Contains(___pawn) && ___pawn.ownership?.OwnedBed == newBed)) { return(true); } // Remove other pawn to make room in bed var pawn = ___pawn; if (newBed.OwnersForReading?.Count == newBed.SleepingSlotsCount && !newBed.OwnersForReading.Any(p => p == pawn) && newBed.OwnersForReading.Count > 0) { var pawnToRemove = newBed.OwnersForReading.LastOrDefault(); pawnToRemove?.ownership?.UnclaimBed(); } // Unclaim bed if pawn already has one on the map of the new bed var pawnBeds = Helpers.PawnBedsOnMap(___pawn, newBed.Map); if (pawnBeds.Any()) { Helpers.UnclaimBeds(___pawn, pawnBeds, ref ___intOwnedBed); } // Claim new bed newBed.CompAssignableToPawn.ForceAddPawn(___pawn); // ... but only assign it if the pawn is on the same map if (___pawn.Map == newBed.Map) { ___intOwnedBed = newBed; ThoughtUtility.RemovePositiveBedroomThoughts(___pawn); } return(false); }
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) { if (!((Building_Bed)actor.CurJob.GetTarget(bedOrRestSpotIndex).Thing).OccupiedRect().Contains(actor.Position)) { Log.Error("Can't start LayDown toil because pawn is not in the bed. pawn=" + actor, false); actor.jobs.EndCurrentJob(JobCondition.Errored, true, true); return; } actor.jobs.posture = PawnPosture.LayingInBed; } else { actor.jobs.posture = PawnPosture.LayingOnGroundNormal; } 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); } CompCanBeDormant comp = actor.GetComp <CompCanBeDormant>(); if (comp != null) { comp.ToSleep(); } }; 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(false); 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 restEffectiveness; if (building_Bed != null && building_Bed.def.statBases.StatListContains(StatDefOf.BedRestEffectiveness)) { restEffectiveness = building_Bed.GetStatValue(StatDefOf.BedRestEffectiveness, true); } else { restEffectiveness = StatDefOf.BedRestEffectiveness.valueIfMissing; } actor.needs.rest.TickResting(restEffectiveness); } 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.OwnersForReading.Contains(actor)) { if (actor.Downed) { actor.Position = CellFinder.RandomClosewalkCellNear(actor.Position, actor.Map, 1, null); } actor.jobs.EndCurrentJob(JobCondition.Incompletable, true, true); return; } if (lookForOtherJobs && actor.IsHashIntervalTick(211)) { actor.jobs.CheckForJobOverride(); return; } }; layDown.AddEndCondition(delegate() { Pawn actor = layDown.actor; if (!actor.health.hediffSet.HasHediff(HediffDefOf.Hypothermia)) { return(JobCondition.Succeeded); } else { return(JobCondition.Ongoing); } }); layDown.defaultCompleteMode = ToilCompleteMode.Never; if (hasBed) { layDown.FailOnBedNoLongerUsable(bedOrRestSpotIndex); } layDown.AddFinishAction(delegate { Pawn actor = layDown.actor; JobDriver curDriver = actor.jobs.curDriver; curDriver.asleep = false; }); return(layDown); }
// A: TargetThing protected override IEnumerable <Toil> MakeNewToils() { yield return(Toils_Bed.ClaimBedIfNonMedical(TargetIndex.A, TargetIndex.None)); yield return(Toils_Bed.GotoBed(TargetIndex.A)); this.goalNeedRest = napRestRate + (1 - napRestRate) * pawn.needs.rest.CurLevelPercentage; Toil nap = new Toil(); nap.defaultCompleteMode = ToilCompleteMode.Never; nap.FailOnBedNoLongerUsable(TargetIndex.A); nap.socialMode = RandomSocialMode.Off; nap.initAction = () => { pawn.pather.StopDead(); if (!Bed.OccupiedRect().Contains(pawn.Position)) { Log.Error("Can't start LayDown toil because pawn is not in the bed. pawn=" + pawn, false); pawn.jobs.EndCurrentJob(JobCondition.Errored, true); return; } pawn.jobs.posture = PawnPosture.LayingInBed; this.asleep = false; if (pawn.mindState.applyBedThoughtsTick == 0) { pawn.mindState.applyBedThoughtsTick = Find.TickManager.TicksGame + Rand.Range(2500, 10000); pawn.mindState.applyBedThoughtsOnLeave = false; } if (pawn.ownership != null && pawn.CurrentBed() != pawn.ownership.OwnedBed) { ThoughtUtility.RemovePositiveBedroomThoughts(pawn); } }; nap.tickAction = () => { pawn.GainComfortFromCellIfPossible(); if (!this.asleep) { if (pawn.needs.rest != null && pawn.needs.rest.CurLevel < RestUtility.FallAsleepMaxLevel(pawn)) { this.asleep = true; } } else if (pawn.needs.rest == null || pawn.needs.rest.CurLevelPercentage >= this.goalNeedRest) { this.asleep = false; } if (this.asleep && pawn.needs.rest != null) { float restEffectiveness; if (Bed != null && Bed.def.statBases.StatListContains(StatDefOf.BedRestEffectiveness)) { restEffectiveness = Bed.GetStatValue(StatDefOf.BedRestEffectiveness, true); } else { restEffectiveness = 0.8f; } pawn.needs.rest.TickResting(restEffectiveness); } if (pawn.mindState.applyBedThoughtsTick != 0 && pawn.mindState.applyBedThoughtsTick <= Find.TickManager.TicksGame) { ApplyBedThoughts(pawn); pawn.mindState.applyBedThoughtsTick += 60000; pawn.mindState.applyBedThoughtsOnLeave = true; } if (pawn.IsHashIntervalTick(100) && !pawn.Position.Fogged(pawn.Map)) { if (this.asleep) { FleckMaker.ThrowMetaIcon(pawn.Position, pawn.Map, FleckDefOf.SleepZ); } if (pawn.health.hediffSet.GetNaturallyHealingInjuredParts().Any <BodyPartRecord>()) { FleckMaker.ThrowMetaIcon(pawn.Position, pawn.Map, FleckDefOf.HealingCross); } } if (pawn.ownership != null && Bed != null && !Bed.Medical && !Bed.OwnersForReading.Contains(pawn)) { if (pawn.Downed) { pawn.Position = CellFinder.RandomClosewalkCellNear(pawn.Position, pawn.Map, 1, null); } pawn.jobs.EndCurrentJob(JobCondition.Incompletable, true); return; } if (pawn.IsHashIntervalTick(211)) { pawn.jobs.CheckForJobOverride(); return; } }; nap.AddFinishAction(() => { if (pawn.mindState.applyBedThoughtsOnLeave) { ApplyBedThoughts(pawn); } this.asleep = false; }); yield return(nap); yield break; }
protected override IEnumerable <Toil> MakeNewToils() { Toil layDown = new Toil(); float num = 1.25f; layDown.initAction = delegate { Pawn actor = layDown.actor; actor.pather.StopDead(); JobDriver curDriver = actor.jobs.curDriver; actor.jobs.posture = PawnPosture.LayingOnGroundNormal; 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; actor.GainComfortFromCellIfPossible(); if (!curDriver.asleep) { if (actor.needs.rest != null && actor.needs.rest.CurLevel < .99f * RestUtility.WakeThreshold(actor)) { curDriver.asleep = true; } } else if (actor.needs.rest == null || actor.needs.rest.CurLevel >= RestUtility.WakeThreshold(actor)) { actor.mindState.priorityWork.ClearPrioritizedWorkAndJobQueue(); this.EndJobWith(JobCondition.Incompletable); } if (curDriver.asleep && actor.needs.rest != null) { num = (0.7f * num) + (0.3f * num); //talk about convoluted calculations... actor.needs.rest.TickResting(num); if (actor.needs.rest.CurLevel >= .99f * RestUtility.WakeThreshold(actor)) { curDriver.asleep = false; actor.mindState.priorityWork.ClearPrioritizedWorkAndJobQueue(); this.EndJobWith(JobCondition.Succeeded); } } if (actor.mindState.applyBedThoughtsTick != 0 && actor.mindState.applyBedThoughtsTick <= Find.TickManager.TicksGame) { 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 (actor.health.hediffSet.GetNaturallyHealingInjuredParts().Any <BodyPartRecord>()) { MoteMaker.ThrowMetaIcon(actor.Position, actor.Map, ThingDefOf.Mote_HealingCross); } } }; layDown.defaultCompleteMode = ToilCompleteMode.Never; layDown.AddFinishAction(delegate { Pawn actor = layDown.actor; JobDriver curDriver = actor.jobs.curDriver; if (actor.mindState.applyBedThoughtsOnLeave) { ApplyBedThoughts(actor); } actor.jobs.posture = PawnPosture.Standing; curDriver.asleep = false; }); yield return(layDown); }
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, false); actor.jobs.EndCurrentJob(JobCondition.Errored, true); return; } actor.jobs.posture = PawnPosture.LayingInBed; } else { actor.jobs.posture = PawnPosture.LayingOnGroundNormal; } 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 (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.OwnersForReading.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; } //Fin recharche ou pod non alimenté ou non operationel if (actor.needs.food.CurLevelPercentage >= 1.0f || building_Bed.Destroyed || building_Bed.IsBrokenDown() || !building_Bed.TryGetComp <CompPowerTrader>().PowerOn) { actor.jobs.EndCurrentJob(JobCondition.Succeeded, true); } }; layDown.defaultCompleteMode = ToilCompleteMode.Never; if (hasBed) { layDown.FailOnBedNoLongerUsable(bedOrRestSpotIndex); } layDown.AddFinishAction(delegate { Pawn actor = layDown.actor; JobDriver curDriver = actor.jobs.curDriver; curDriver.asleep = false; }); return(layDown); }
public static Toil BrrrLayDown(TargetIndex bedOrRestSpotIndex, bool hasBed, bool lookForOtherJobs = false, bool canSleep = true, bool gainRestAndHealth = true) { var layDown = new Toil(); layDown.initAction = delegate { var actor3 = layDown.actor; actor3.pather.StopDead(); var curDriver3 = actor3.jobs.curDriver; if (hasBed) { if (!((Building_Bed)actor3.CurJob.GetTarget(bedOrRestSpotIndex).Thing).OccupiedRect() .Contains(actor3.Position)) { Log.Error("Can't start LayDown toil because pawn is not in the bed. pawn=" + actor3); actor3.jobs.EndCurrentJob(JobCondition.Errored); return; } actor3.jobs.posture = PawnPosture.LayingInBed; } else { actor3.jobs.posture = PawnPosture.LayingOnGroundNormal; } curDriver3.asleep = false; if (actor3.mindState.applyBedThoughtsTick == 0) { actor3.mindState.applyBedThoughtsTick = Find.TickManager.TicksGame + Rand.Range(2500, 10000); actor3.mindState.applyBedThoughtsOnLeave = false; } if (actor3.ownership != null && actor3.CurrentBed() != actor3.ownership.OwnedBed) { ThoughtUtility.RemovePositiveBedroomThoughts(actor3); } }; layDown.tickAction = delegate { var actor2 = layDown.actor; var curJob = actor2.CurJob; var curDriver2 = actor2.jobs.curDriver; var building_Bed = (Building_Bed)curJob.GetTarget(bedOrRestSpotIndex).Thing; actor2.GainComfortFromCellIfPossible(); if (!curDriver2.asleep) { if (canSleep && (actor2.needs.rest != null && actor2.needs.rest.CurLevel < RestUtility.FallAsleepMaxLevel(actor2) || curJob.forceSleep)) { curDriver2.asleep = true; } } else if (!canSleep) { curDriver2.asleep = false; } else if ((actor2.needs.rest == null || actor2.needs.rest.CurLevel >= RestUtility.WakeThreshold(actor2)) && !curJob.forceSleep) { curDriver2.asleep = false; } if (curDriver2.asleep & gainRestAndHealth && actor2.needs.rest != null) { var restEffectiveness = building_Bed == null || !building_Bed.def.statBases.StatListContains(StatDefOf.BedRestEffectiveness) ? 0.8f : building_Bed.GetStatValue(StatDefOf.BedRestEffectiveness); actor2.needs.rest.TickResting(restEffectiveness); } if (actor2.mindState.applyBedThoughtsTick != 0 && actor2.mindState.applyBedThoughtsTick <= Find.TickManager.TicksGame) { ApplyBedThoughts(actor2); actor2.mindState.applyBedThoughtsTick += 60000; actor2.mindState.applyBedThoughtsOnLeave = true; } if (actor2.IsHashIntervalTick(TicksBetweenSleepZs) && !actor2.Position.Fogged(actor2.Map)) { if (curDriver2.asleep) { FleckMaker.ThrowMetaIcon(actor2.Position, actor2.Map, FleckDefOf.SleepZ); } if (gainRestAndHealth && actor2.health.hediffSet.GetNaturallyHealingInjuredParts().Any()) { FleckMaker.ThrowMetaIcon(actor2.Position, actor2.Map, FleckDefOf.HealingCross); } } if (actor2.ownership != null && building_Bed != null && !building_Bed.Medical && !building_Bed.OwnersForReading.Contains(actor2)) { if (actor2.Downed) { actor2.Position = CellFinder.RandomClosewalkCellNear(actor2.Position, actor2.Map, 1); } actor2.jobs.EndCurrentJob(JobCondition.Incompletable); return; } if (lookForOtherJobs && actor2.IsHashIntervalTick(GetUpOrStartJobWhileInBedCheckInterval)) { actor2.jobs.CheckForJobOverride(); } }; layDown.defaultCompleteMode = ToilCompleteMode.Never; if (hasBed) { layDown.FailOnBedNoLongerUsable(bedOrRestSpotIndex); } layDown.AddFailCondition(delegate { var actor = layDown.actor; var needs = actor.needs; if (needs?.food != null && actor.needs.food.CurLevelPercentage < actor.needs.food.PercentageThreshHungry) { return(true); } var needs2 = actor.needs; return(needs2?.joy != null && !actor.RaceProps.Animal && actor.needs.joy.CurLevelPercentage < Settings.JoySev / 100f && Settings.AllowJoy); }); layDown.AddFailCondition(delegate { var actor = layDown.actor; var hypoHed = actor.health.hediffSet.GetFirstHediffOfDef(HediffDefOf.Hypothermia); var heatHed = actor.health.hediffSet.GetFirstHediffOfDef(HediffDefOf.Heatstroke); var ToxHed = actor.health.hediffSet.GetFirstHediffOfDef(HediffDefOf.ToxicBuildup); var BreathHed = actor.health.hediffSet.GetFirstHediffOfDef( DefDatabase <HediffDef> .GetNamed("OxygenStarvation", false)); return(hypoHed == null && heatHed == null && ToxHed == null && BreathHed == null); }); layDown.AddFinishAction(delegate { var actor = layDown.actor; var curDriver = actor.jobs.curDriver; if (actor.mindState.applyBedThoughtsOnLeave) { ApplyBedThoughts(actor); } curDriver.asleep = false; }); return(layDown); }