This commit is contained in:
2025-08-11 21:22:41 +08:00
parent f8154ca5c1
commit 75561a846a
901 changed files with 22639 additions and 4 deletions

View File

@@ -0,0 +1,827 @@
根据向量相似度分析,与 'JobDriver_TakeToBed, Rescue, JobDefOf' 最相关的代码定义如下:
---
**文件路径 (精确匹配):** `C:\Steam\steamapps\common\RimWorld\Data\dll1.6\RimWorld\JobDriver_TakeToBed.txt`
```csharp
public class JobDriver_TakeToBed : JobDriver
{
private const TargetIndex TakeeIndex = TargetIndex.A;
private const TargetIndex BedIndex = TargetIndex.B;
protected Pawn Takee => (Pawn)job.GetTarget(TargetIndex.A).Thing;
protected Building_Bed DropBed => (Building_Bed)job.GetTarget(TargetIndex.B).Thing;
private bool TakeeRescued
{
get
{
if (Takee.RaceProps.Humanlike && job.def != JobDefOf.Arrest && !Takee.IsPrisonerOfColony)
{
if (Takee.ageTracker.CurLifeStage.alwaysDowned)
{
return HealthAIUtility.ShouldSeekMedicalRest(Takee);
}
return true;
}
return false;
}
}
public override string GetReport()
{
if (job.def == JobDefOf.Rescue && !TakeeRescued)
{
return "TakingToBed".Translate(Takee);
}
return base.GetReport();
}
public override bool TryMakePreToilReservations(bool errorOnFailed)
{
Takee.ClearAllReservations();
if (pawn.Reserve(Takee, job, 1, -1, null, errorOnFailed))
{
return pawn.Reserve(DropBed, job, DropBed.SleepingSlotsCount, 0, null, errorOnFailed);
}
return false;
}
protected override IEnumerable<Toil> MakeNewToils()
{
this.FailOnDestroyedOrNull(TargetIndex.A);
this.FailOnDestroyedOrNull(TargetIndex.B);
this.FailOnAggroMentalStateAndHostile(TargetIndex.A);
this.FailOn(delegate
{
if (job.def.makeTargetPrisoner)
{
if (!DropBed.ForPrisoners)
{
return true;
}
}
else if (DropBed.ForPrisoners != Takee.IsPrisoner)
{
return true;
}
return false;
});
yield return Toils_Bed.ClaimBedIfNonMedical(TargetIndex.B, TargetIndex.A);
AddFinishAction(delegate
{
if (job.def.makeTargetPrisoner && Takee.ownership.OwnedBed == DropBed && Takee.Position != RestUtility.GetBedSleepingSlotPosFor(Takee, DropBed))
{
Takee.ownership.UnclaimBed();
}
if (pawn.carryTracker.CarriedThing != null)
{
pawn.carryTracker.TryDropCarriedThing(pawn.Position, ThingPlaceMode.Direct, out var _);
}
});
Toil goToTakee = Toils_Goto.GotoThing(TargetIndex.A, PathEndMode.ClosestTouch).FailOnDespawnedNullOrForbidden(TargetIndex.A).FailOnDespawnedNullOrForbidden(TargetIndex.B)
.FailOn(() => job.def == JobDefOf.Arrest && !Takee.CanBeArrestedBy(pawn))
.FailOn(() => !pawn.CanReach(DropBed, PathEndMode.OnCell, Danger.Deadly))
.FailOn(() => (job.def == JobDefOf.Rescue || job.def == JobDefOf.Capture) && !Takee.Downed)
.FailOnSomeonePhysicallyInteracting(TargetIndex.A);
Toil checkArrestResistance = ToilMaker.MakeToil("MakeNewToils");
checkArrestResistance.initAction = delegate
{
if (job.def.makeTargetPrisoner)
{
Pawn pawn = (Pawn)job.targetA.Thing;
pawn.GetLord()?.Notify_PawnAttemptArrested(pawn);
GenClamor.DoClamor(pawn, 10f, ClamorDefOf.Harm);
if (!pawn.IsPrisoner && !pawn.IsSlave)
{
QuestUtility.SendQuestTargetSignals(pawn.questTags, "Arrested", pawn.Named("SUBJECT"));
if (pawn.Faction != null)
{
QuestUtility.SendQuestTargetSignals(pawn.Faction.questTags, "FactionMemberArrested", pawn.Faction.Named("FACTION"));
}
}
if (job.def == JobDefOf.Arrest && !pawn.CheckAcceptArrest(base.pawn))
{
base.pawn.jobs.EndCurrentJob(JobCondition.Incompletable);
}
}
};
yield return Toils_Jump.JumpIf(checkArrestResistance, () => pawn.IsCarryingPawn(Takee));
yield return goToTakee;
yield return checkArrestResistance;
Toil startCarrying = Toils_Haul.StartCarryThing(TargetIndex.A);
startCarrying.FailOnBedNoLongerUsable(TargetIndex.B, TargetIndex.A);
startCarrying.AddPreInitAction(CheckMakeTakeeGuest);
startCarrying.AddFinishAction(delegate
{
if (pawn.Faction == Takee.Faction)
{
CheckMakeTakeePrisoner();
}
});
Toil goToBed = Toils_Goto.GotoThing(TargetIndex.B, PathEndMode.Touch).FailOn(() => !pawn.IsCarryingPawn(Takee));
goToBed.FailOnBedNoLongerUsable(TargetIndex.B, TargetIndex.A);
yield return Toils_Jump.JumpIf(goToBed, () => pawn.IsCarryingPawn(Takee));
yield return startCarrying;
yield return goToBed;
Toil toil = ToilMaker.MakeToil("MakeNewToils");
toil.initAction = delegate
{
CheckMakeTakeePrisoner();
if (Takee.playerSettings == null)
{
Takee.playerSettings = new Pawn_PlayerSettings(Takee);
}
};
yield return toil;
yield return Toils_Reserve.Release(TargetIndex.B);
yield return Toils_Bed.TuckIntoBed(DropBed, pawn, Takee, TakeeRescued);
yield return Toils_General.Do(delegate
{
if (!job.ritualTag.NullOrEmpty())
{
if (Takee.GetLord()?.LordJob is LordJob_Ritual lordJob_Ritual)
{
lordJob_Ritual.AddTagForPawn(Takee, job.ritualTag);
}
if (pawn.GetLord()?.LordJob is LordJob_Ritual lordJob_Ritual2)
{
lordJob_Ritual2.AddTagForPawn(pawn, job.ritualTag);
}
}
});
}
private void CheckMakeTakeePrisoner()
{
if (job.def.makeTargetPrisoner)
{
if (Takee.guest.Released)
{
Takee.guest.Released = false;
Takee.guest.SetExclusiveInteraction(PrisonerInteractionModeDefOf.MaintainOnly);
GenGuest.RemoveHealthyPrisonerReleasedThoughts(Takee);
}
if (!Takee.IsPrisonerOfColony)
{
Takee.guest.CapturedBy(Faction.OfPlayer, pawn);
}
}
}
private void CheckMakeTakeeGuest()
{
if (!job.def.makeTargetPrisoner && Takee.Faction != Faction.OfPlayer && Takee.HostFaction != Faction.OfPlayer && Takee.guest != null && !Takee.IsWildMan() && Takee.DevelopmentalStage != DevelopmentalStage.Baby)
{
Takee.guest.SetGuestStatus(Faction.OfPlayer);
QuestUtility.SendQuestTargetSignals(Takee.questTags, "Rescued", Takee.Named("SUBJECT"));
}
}
}
```
---
**文件路径:** `C:\Steam\steamapps\common\RimWorld\Data\Core\Defs\JobDefs\Jobs_Work.xml`
**相似度:** 0.6607
```xml
<defName>Rescue</defName>
<driverClass>JobDriver_TakeToBed</driverClass>
<reportString>rescuing TargetA.</reportString>
<casualInterruptible>false</casualInterruptible>
<carryThingAfterJob>true</carryThingAfterJob>
<dropThingBeforeJob>false</dropThingBeforeJob>
</JobDef>
<JobDef>
<defName>CarryToCryptosleepCasket</defName>
```
---
**文件路径:** `C:\Steam\steamapps\common\RimWorld\Data\Core\Defs\JobDefs\Jobs_Misc.xml`
**相似度:** 0.6320
```xml
<defName>DeliverToBed</defName>
<driverClass>JobDriver_TakeToBed</driverClass>
<reportString>delivering TargetA.</reportString>
<casualInterruptible>false</casualInterruptible>
</JobDef>
<JobDef>
<defName>TakeCountToInventory</defName>
```
---
**文件路径:** `C:\Steam\steamapps\common\RimWorld\Data\dll1.6\RimWorld\RestUtility.txt`
**相似度:** 0.5085
```csharp
public static class RestUtility
{
public const int NoSleepingDurationAfterBeingDisturbed = 400;
private static List<ThingDef> bedDefsBestToWorst_RestEffectiveness;
private static List<ThingDef> bedDefsBestToWorst_Medical;
private static List<ThingDef> bedDefsBestToWorst_SlabBed_RestEffectiveness;
private static List<ThingDef> bedDefsBestToWorst_SlabBed_Medical;
public static List<ThingDef> AllBedDefBestToWorst => bedDefsBestToWorst_RestEffectiveness;
public static void Reset()
{
bedDefsBestToWorst_RestEffectiveness = (from d in DefDatabase<ThingDef>.AllDefs
where d.IsBed
orderby d.building.bed_maxBodySize, d.GetStatValueAbstract(StatDefOf.BedRestEffectiveness) descending
select d).ToList();
bedDefsBestToWorst_SlabBed_RestEffectiveness = (from d in DefDatabase<ThingDef>.AllDefs
where d.IsBed
orderby (!d.building.bed_slabBed) ? 1 : 0, d.building.bed_maxBodySize, d.GetStatValueAbstract(StatDefOf.BedRestEffectiveness) descending
select d).ToList();
bedDefsBestToWorst_Medical = (from d in DefDatabase<ThingDef>.AllDefs
where d.IsBed
orderby d.building.bed_maxBodySize, d.GetStatValueAbstract(StatDefOf.MedicalTendQualityOffset) descending, d.GetStatValueAbstract(StatDefOf.BedRestEffectiveness) descending
select d).ToList();
bedDefsBestToWorst_SlabBed_Medical = (from d in DefDatabase<ThingDef>.AllDefs
where d.IsBed
orderby (!d.building.bed_slabBed) ? 1 : 0, d.building.bed_maxBodySize, d.GetStatValueAbstract(StatDefOf.MedicalTendQualityOffset) descending, d.GetStatValueAbstract(StatDefOf.BedRestEffectiveness) descending
select d).ToList();
}
public static bool BedOwnerWillShare(Building_Bed bed, Pawn sleeper, GuestStatus? guestStatus)
{
if (!bed.OwnersForReading.Any())
{
return true;
}
if (sleeper.IsPrisoner || guestStatus == GuestStatus.Prisoner || sleeper.IsSlave || guestStatus == GuestStatus.Slave)
{
if (!bed.AnyUnownedSleepingSlot)
{
return false;
}
}
else
{
if (!bed.AnyUnownedSleepingSlot)
{
return false;
}
if (!IsAnyOwnerLovePartnerOf(bed, sleeper))
{
return false;
}
}
return true;
}
public static bool CanUseBedNow(Thing bedThing, Pawn sleeper, bool checkSocialProperness, bool allowMedBedEvenIfSetToNoCare = false, GuestStatus? guestStatusOverride = null)
{
if (!(bedThing is Building_Bed building_Bed))
{
return false;
}
if (!building_Bed.Spawned)
{
return false;
}
if (building_Bed.Map != sleeper.MapHeld)
{
return false;
}
if (building_Bed.IsBurning())
{
return false;
}
if (sleeper.HarmedByVacuum && building_Bed.Position.GetVacuum(bedThing.Map) >= 0.5f)
{
return false;
}
if (!CanUseBedEver(sleeper, building_Bed.def))
{
return false;
}
if (building_Bed.CompAssignableToPawn.IdeoligionForbids(sleeper))
{
return false;
}
int? assignedSleepingSlot;
bool flag = building_Bed.IsOwner(sleeper, out assignedSleepingSlot);
int? sleepingSlot;
bool flag2 = sleeper.CurrentBed(out sleepingSlot) == building_Bed;
if (!building_Bed.AnyUnoccupiedSleepingSlot && !flag && !flag2)
{
return false;
}
GuestStatus? obj = guestStatusOverride ?? sleeper.GuestStatus;
bool flag3 = obj == GuestStatus.Prisoner;
bool flag4 = obj == GuestStatus.Slave;
if (checkSocialProperness && !building_Bed.IsSociallyProper(sleeper, flag3))
{
return false;
}
if (building_Bed.ForPrisoners != flag3)
{
return false;
}
if (building_Bed.ForSlaves != flag4)
{
return false;
}
if (building_Bed.ForPrisoners && !building_Bed.Position.IsInPrisonCell(building_Bed.Map))
{
return false;
}
if (building_Bed.Medical)
{
if (!allowMedBedEvenIfSetToNoCare && !HealthAIUtility.ShouldEverReceiveMedicalCareFromPlayer(sleeper))
{
return false;
}
if (!HealthAIUtility.ShouldSeekMedicalRest(sleeper))
{
return false;
}
}
else
{
if (!flag && !BedOwnerWillShare(building_Bed, sleeper, guestStatusOverride))
{
return false;
}
if (flag2 && sleepingSlot != assignedSleepingSlot)
{
return false;
}
}
if (sleeper.IsColonist && !flag3)
{
Job curJob = sleeper.CurJob;
if ((curJob == null || !curJob.ignoreForbidden) && !sleeper.Downed && building_Bed.IsForbidden(sleeper))
{
return false;
}
}
return true;
}
public static bool IsValidBedFor(Thing bedThing, Pawn sleeper, Pawn traveler, bool checkSocialProperness, bool allowMedBedEvenIfSetToNoCare = false, bool ignoreOtherReservations = false, GuestStatus? guestStatus = null)
{
if (!CanUseBedNow(bedThing, sleeper, checkSocialProperness, allowMedBedEvenIfSetToNoCare, guestStatus))
{
return false;
}
Building_Bed building_Bed = (Building_Bed)bedThing;
if (!traveler.CanReach(building_Bed, PathEndMode.OnCell, Danger.Some))
{
return false;
}
if (!sleeper.HasReserved(building_Bed) && !traveler.CanReserve(building_Bed, building_Bed.SleepingSlotsCount, 0, null, ignoreOtherReservations))
{
return false;
}
if (traveler.HasReserved<JobDriver_TakeToBed>(building_Bed, sleeper))
{
return false;
}
if (building_Bed.IsForbidden(traveler))
{
return false;
}
bool num = guestStatus == GuestStatus.Prisoner;
bool flag = guestStatus == GuestStatus.Slave;
if (!num && !flag && building_Bed.Faction != traveler.Faction && (traveler.HostFaction == null || building_Bed.Faction != traveler.HostFaction))
{
return false;
}
if (ModsConfig.AnomalyActive && sleeper.IsMutant && sleeper.needs.rest == null && sleeper.mutant.Def.entitledToMedicalCare && !building_Bed.Medical)
{
return false;
}
return true;
}
public static void TuckIntoBed(Building_Bed bed, Pawn taker, Pawn takee, bool rescued)
{
IntVec3 position = bed.Position;
if (taker != takee)
{
taker.carryTracker.TryDropCarriedThing(position, ThingPlaceMode.Direct, out var _);
}
if (CanUseBedNow(bed, takee, checkSocialProperness: false))
{
takee.jobs.Notify_TuckedIntoBed(bed);
if (taker != takee && rescued)
{
takee.relations.Notify_RescuedBy(taker);
}
takee.mindState.Notify_TuckedIntoBed();
}
if (takee.IsPrisonerOfColony)
{
LessonAutoActivator.TeachOpportunity(ConceptDefOf.PrisonerTab, takee, OpportunityType.GoodToKnow);
}
}
private static bool IsAnyOwnerLovePartnerOf(Building_Bed bed, Pawn sleeper)
{
for (int i = 0; i < bed.OwnersForReading.Count; i++)
{
if (LovePartnerRelationUtility.LovePartnerRelationExists(sleeper, bed.OwnersForReading[i]))
{
return true;
}
}
return false;
}
public static Building_Bed FindBedFor(Pawn p)
{
return FindBedFor(p, p, checkSocialProperness: true, ignoreOtherReservations: false, p.GuestStatus);
}
public static Building_Bed FindBedFor(Pawn sleeper, Pawn traveler, bool checkSocialProperness, bool ignoreOtherReservations = false, GuestStatus? guestStatus = null)
{
if (sleeper.RaceProps.IsMechanoid)
{
return null;
}
if (ModsConfig.BiotechActive && sleeper.Deathresting)
{
Building_Bed assignedDeathrestCasket = sleeper.ownership.AssignedDeathrestCasket;
if (assignedDeathrestCasket != null && IsValidBedFor(assignedDeathrestCasket, sleeper, traveler, checkSocialProperness: true))
{
CompDeathrestBindable compDeathrestBindable = assignedDeathrestCasket.TryGetComp<CompDeathrestBindable>();
if (compDeathrestBindable != null && (compDeathrestBindable.BoundPawn == sleeper || compDeathrestBindable.BoundPawn == null))
{
return assignedDeathrestCasket;
}
}
}
bool flag = false;
if (sleeper.Ideo != null)
{
foreach (Precept item in sleeper.Ideo.PreceptsListForReading)
{
if (item.def.prefersSlabBed)
{
flag = true;
break;
}
}
}
List<ThingDef> list = (flag ? bedDefsBestToWorst_SlabBed_Medical : bedDefsBestToWorst_Medical);
List<ThingDef> list2 = (flag ? bedDefsBestToWorst_SlabBed_RestEffectiveness : bedDefsBestToWorst_RestEffectiveness);
if (HealthAIUtility.ShouldSeekMedicalRest(sleeper))
{
if (sleeper.InBed() && sleeper.CurrentBed().Medical && IsValidBedFor(sleeper.CurrentBed(), sleeper, traveler, checkSocialProperness, allowMedBedEvenIfSetToNoCare: false, ignoreOtherReservations, guestStatus))
{
return sleeper.CurrentBed();
}
for (int i = 0; i < list.Count; i++)
{
ThingDef thingDef = list[i];
if (!CanUseBedEver(sleeper, thingDef))
{
continue;
}
for (int j = 0; j < 2; j++)
{
Danger maxDanger = ((j == 0) ? Danger.None : Danger.Deadly);
Building_Bed building_Bed = (Building_Bed)GenClosest.ClosestThingReachable(sleeper.Position, sleeper.MapHeld, ThingRequest.ForDef(thingDef), PathEndMode.OnCell, TraverseParms.For(traveler), 9999f, (Thing b) => ((Building_Bed)b).Medical && (int)b.Position.GetDangerFor(sleeper, sleeper.Map) <= (int)maxDanger && IsValidBedFor(b, sleeper, traveler, checkSocialProperness, allowMedBedEvenIfSetToNoCare: false, ignoreOtherReservations, guestStatus));
if (building_Bed != null)
{
return building_Bed;
}
}
}
}
if (sleeper.RaceProps.Dryad)
{
return null;
}
if (sleeper.ownership != null && sleeper.ownership.OwnedBed != null && IsValidBedFor(sleeper.ownership.OwnedBed, sleeper, traveler, checkSocialProperness, allowMedBedEvenIfSetToNoCare: false, ignoreOtherReservations, guestStatus))
{
return sleeper.ownership.OwnedBed;
}
DirectPawnRelation directPawnRelation = LovePartnerRelationUtility.ExistingMostLikedLovePartnerRel(sleeper, allowDead: false);
if (directPawnRelation != null)
{
Building_Bed ownedBed = directPawnRelation.otherPawn.ownership.OwnedBed;
if (ownedBed != null && IsValidBedFor(ownedBed, sleeper, traveler, checkSocialProperness, allowMedBedEvenIfSetToNoCare: false, ignoreOtherReservations, guestStatus))
{
return ownedBed;
}
}
for (int dg = 0; dg < 3; dg++)
{
Danger maxDanger = ((dg <= 1) ? Danger.None : Danger.Deadly);
for (int k = 0; k < list2.Count; k++)
{
ThingDef thingDef2 = list2[k];
if (!CanUseBedEver(sleeper, thingDef2))
{
continue;
}
Building_Bed building_Bed2 = (Building_Bed)GenClosest.ClosestThingReachable(sleeper.PositionHeld, sleeper.MapHeld, ThingRequest.ForDef(thingDef2), PathEndMode.OnCell, TraverseParms.For(traveler), 9999f, (Thing b) => !((Building_Bed)b).Medical && (int)b.Position.GetDangerFor(sleeper, sleeper.MapHeld) <= (int)maxDanger && IsValidBedFor(b, sleeper, traveler, checkSocialProperness, allowMedBedEvenIfSetToNoCare: false, ignoreOtherReservations, guestStatus) && (dg > 0 || !b.Position.GetItems(b.Map).Any((Thing thing) => thing.def.IsCorpse)));
if (building_Bed2 != null)
{
return building_Bed2;
}
}
}
return null;
}
public static Building_Bed FindPatientBedFor(Pawn pawn)
{
Predicate<Thing> medBedValidator = delegate(Thing t)
{
if (!(t is Building_Bed building_Bed2))
{
return false;
}
if (!building_Bed2.Medical)
{
return false;
}
return IsValidBedFor(building_Bed2, pawn, pawn, checkSocialProperness: false, allowMedBedEvenIfSetToNoCare: true, ignoreOtherReservations: false, pawn.GuestStatus) ? true : false;
};
if (pawn.InBed() && medBedValidator(pawn.CurrentBed()))
{
return pawn.CurrentBed();
}
for (int i = 0; i < 2; i++)
{
Danger maxDanger = ((i == 0) ? Danger.None : Danger.Deadly);
Building_Bed building_Bed = (Building_Bed)GenClosest.ClosestThingReachable(pawn.Position, pawn.Map, ThingRequest.ForGroup(ThingRequestGroup.Bed), PathEndMode.OnCell, TraverseParms.For(pawn), 9999f, (Thing b) => (int)b.Position.GetDangerFor(pawn, pawn.Map) <= (int)maxDanger && medBedValidator(b));
if (building_Bed != null)
{
return building_Bed;
}
}
return FindBedFor(pawn);
}
public static IntVec3 GetBedSleepingSlotPosFor(Pawn pawn, Building_Bed bed)
{
if (bed.IsOwner(pawn, out var assignedSleepingSlot))
{
return bed.GetSleepingSlotPos(assignedSleepingSlot.Value);
}
for (int i = 0; i < bed.SleepingSlotsCount; i++)
{
Pawn curOccupant = bed.GetCurOccupant(i);
if ((i >= bed.OwnersForReading.Count || bed.OwnersForReading[i] == null) && curOccupant == pawn)
{
return bed.GetSleepingSlotPos(i);
}
}
for (int j = 0; j < bed.SleepingSlotsCount; j++)
{
Pawn curOccupant2 = bed.GetCurOccupant(j);
if ((j >= bed.OwnersForReading.Count || bed.OwnersForReading[j] == null) && curOccupant2 == null)
{
return bed.GetSleepingSlotPos(j);
}
}
Log.Error("Could not find good sleeping slot position for " + pawn?.ToString() + ". Perhaps AnyUnoccupiedSleepingSlot check is missing somewhere.");
return bed.GetSleepingSlotPos(0);
}
public static void KickOutOfBed(Pawn pawn, Building_Bed bed)
{
if (pawn == null)
{
return;
}
if (!pawn.Spawned)
{
Log.Error("Tried to kick unspawned pawn " + pawn.ToStringSafe() + " out of bed.");
}
if (!pawn.Dead && !pawn.GetPosture().InBed())
{
Log.Error("Tried to kick pawn " + pawn.ToStringSafe() + " out of bed when they weren't in bed.");
}
int? sleepingSlot;
Building_Bed building_Bed = pawn.CurrentBed(out sleepingSlot);
if (building_Bed != bed)
{
if (building_Bed == null)
{
bed = null;
}
else
{
Log.Error("Tried to kick pawn " + pawn.ToStringSafe() + " out of a bed they're not currently in.");
}
}
pawn.jobs.posture &= ~PawnPosture.InBedMask;
if (bed != null && (pawn.Downed || pawn.Deathresting))
{
pawn.Position = bed.GetFootSlotPos(sleepingSlot.Value);
}
}
public static bool CanUseBedEver(Pawn p, ThingDef bedDef)
{
if (p.RaceProps.IsMechanoid)
{
return false;
}
if (p.BodySize > bedDef.building.bed_maxBodySize)
{
return false;
}
if (p.RaceProps.Humanlike != bedDef.building.bed_humanlike)
{
return false;
}
if (ModsConfig.BiotechActive && bedDef == ThingDefOf.DeathrestCasket && !p.CanDeathrest())
{
return false;
}
return true;
}
public static bool TimetablePreventsLayDown(Pawn pawn)
{
if (pawn.timetable?.CurrentAssignment != null && !pawn.timetable.CurrentAssignment.allowRest && pawn.needs?.rest != null && pawn.needs.rest.CurLevel >= 0.2f)
{
return true;
}
return false;
}
public static bool DisturbancePreventsLyingDown(Pawn pawn)
{
if (pawn.Downed)
{
return false;
}
return Find.TickManager.TicksGame - pawn.mindState.lastDisturbanceTick < 400;
}
public static bool Awake(this Pawn p)
{
if (!p.health.capacities.CanBeAwake)
{
return false;
}
if (p.CurJob != null && p.jobs.curDriver != null)
{
return !p.jobs.curDriver.asleep;
}
return true;
}
public static bool IsSelfShutdown(this Pawn p)
{
if (p.needs?.energy == null)
{
return false;
}
return p.needs.energy.IsSelfShutdown;
}
public static bool IsDeactivated(this Pawn p)
{
return p.TryGetComp<CompMechanoid>()?.Deactivated ?? false;
}
public static bool IsActivityDormant(this Pawn p)
{
if (p.GetComp<CompActivity>() == null)
{
return false;
}
return p.GetComp<CompActivity>().IsActive;
}
public static bool IsCharging(this Pawn p)
{
return p.needs?.energy?.currentCharger != null;
}
public static Building_Bed CurrentBed(this Pawn p)
{
int? sleepingSlot;
return p.CurrentBed(out sleepingSlot);
}
public static Building_Bed CurrentBed(this Pawn p, out int? sleepingSlot)
{
sleepingSlot = null;
if (!p.Spawned || p.CurJob == null || !p.GetPosture().InBed())
{
return null;
}
Building_Bed building_Bed = null;
List<Thing> thingList = p.Position.GetThingList(p.Map);
for (int i = 0; i < thingList.Count; i++)
{
building_Bed = thingList[i] as Building_Bed;
if (building_Bed != null)
{
break;
}
}
if (building_Bed == null)
{
return null;
}
for (int j = 0; j < building_Bed.SleepingSlotsCount; j++)
{
if (building_Bed.GetCurOccupant(j) == p)
{
sleepingSlot = j;
return building_Bed;
}
}
return null;
}
public static bool InBed(this Pawn p)
{
return p.CurrentBed() != null;
}
public static bool IsLayingForJobCleanup(Pawn p)
{
if (!p.InBed())
{
if (p.CurJob != null && p.CurJob.def == JobDefOf.LayDown)
{
return p.GetPosture().Laying();
}
return false;
}
return true;
}
public static void WakeUp(Pawn p, bool startNewJob = true)
{
if (p.CurJob != null && (p.GetPosture().Laying() || p.CurJobDef == JobDefOf.LayDown) && !p.Downed)
{
p.jobs.EndCurrentJob(JobCondition.InterruptForced, startNewJob);
}
p.GetComp<CompCanBeDormant>()?.WakeUp();
if (p.mindState != null)
{
p.mindState.hibernationEndedTick = GenTicks.TicksGame;
}
}
public static bool ShouldWakeUp(Pawn pawn)
{
if (pawn.Deathresting)
{
return false;
}
if (pawn.needs?.rest != null && !(pawn.needs.rest.CurLevel >= WakeThreshold(pawn)))
{
return pawn.health.hediffSet.HasHediffBlocksSleeping();
}
return true;
}
public static bool CanFallAsleep(Pawn pawn)
{
if (pawn.Deathresting)
{
return true;
}
Pawn_NeedsTracker needs = pawn.needs;
if (needs != null && needs.food?.Starving == true && !pawn.ageTracker.CurLifeStage.canSleepWhenStarving)
{
return false;
}
if (pawn.mindState != null && Find.TickManager.TicksGame - pawn.mindState.lastDisturbanceTick < 400)
{
return false;
}
if (pawn.needs?.rest?.CurLevel < FallAsleepMaxLevel(pawn) && !pawn.health.hediffSet.HasHediffBlocksSleeping())
{
return pawn.CurJobDef?.sleepCanInterrupt ?? true;
}
return false;
}
private static float WakeThreshold(Pawn p)
{
Lord lord = p.GetLord();
if (lord != null && lord.CurLordToil != null && lord.CurLordToil.CustomWakeThreshold.HasValue)
{
return lord.CurLordToil.CustomWakeThreshold.Value;
}
return p.ageTracker.CurLifeStage?.naturalWakeThresholdOverride ?? 1f;
}
private static float FallAsleepMaxLevel(Pawn p)
{
return Mathf.Min(p.ageTracker.CurLifeStage?.fallAsleepMaxThresholdOverride ?? 0.75f, WakeThreshold(p) - 0.01f);
}
}
```