本文整理汇总了C#中Pawn.CanReach方法的典型用法代码示例。如果您正苦于以下问题:C# Pawn.CanReach方法的具体用法?C# Pawn.CanReach怎么用?C# Pawn.CanReach使用的例子?那么, 这里精选的方法代码示例或许可以为您提供帮助。您也可以进一步了解该方法所在类Pawn
的用法示例。
在下文中一共展示了Pawn.CanReach方法的15个代码示例,这些例子默认根据受欢迎程度排序。您可以为喜欢或者感觉有用的代码点赞,您的评价将有助于系统推荐出更棒的C#代码示例。
示例1: TryGiveTerminalJob
protected override Job TryGiveTerminalJob(Pawn pawn)
{
// Log.Message("Scratching the itch.");
// try finding scratching poles.
Thing target = GenClosest.ClosestThingReachable(pawn.Position, ThingRequest.ForDef(ThingDef.Named("Fluffy_ScratchingPole")), PathEndMode.Touch, TraverseParms.For(pawn), 20);
if (target != null)
{
// Log.Message("Scratching pole found.");
return new Job(DefDatabase<JobDef>.GetNamed("Fluffy_Scratch", true), target);
}
// potential other targets.
IEnumerable<Building> targets = from t in Find.ListerBuildings.AllBuildingsColonistOfClass<Building>()
where t.def.useHitPoints
&& pawn.CanReach(new TargetInfo(t), PathEndMode.Touch, Danger.Some)
select t;
if (!targets.Any())
{
return null;
}
target = targets.RandomElement();
// Log.Message("Furniture found.");
return new Job(DefDatabase<JobDef>.GetNamed("Fluffy_Scratch", true), target);
}
示例2: TryGiveTerminalJob
protected override Job TryGiveTerminalJob(Pawn pawn)
{
Thing thing = this.FindPawnTarget(pawn);
if (thing == null)
{
thing = this.FindTurretTarget(pawn);
}
if (thing == null)
{
return null;
}
if (thing.Position.AdjacentTo8Way(pawn.Position))
{
return this.MeleeAttackJob(pawn, thing);
}
if (thing != null && pawn.CanReach(thing, PathEndMode.Touch, Danger.Deadly, false) && HasRangedVerb(pawn))
{
return this.RangedAttackJob(pawn, thing);
}
if (thing != null && pawn.CanReach(thing, PathEndMode.Touch, Danger.Deadly, false))
{
return this.MeleeAttackJob(pawn, thing);
}
PawnPath pawnPath = PathFinder.FindPath(pawn.Position, thing.Position, TraverseParms.For(pawn, Danger.Deadly, TraverseMode.PassDoors, false), PathEndMode.OnCell);
if (!pawnPath.Found)
{
return null;
}
IntVec3 randomCell;
try
{
IntVec3 loc;
if (!pawnPath.TryFindLastCellBeforeBlockingDoor(out loc))
{
Log.Error(pawn + " did TryFindLastCellBeforeDoor but found none when it should have been one.");
return null;
}
randomCell = CellFinder.RandomRegionNear(loc.GetRegion(), 9, TraverseParms.For(pawn, Danger.Deadly, TraverseMode.ByPawn, false), null, null).RandomCell;
}
finally
{
pawnPath.ReleaseToPool();
}
return new Job(JobDefOf.Goto, randomCell);
}
示例3: TryGiveJob
protected override Job TryGiveJob(Pawn pawn)
{
var cell = pawn.mindState.duty.focus.Cell;
if (pawn.Position == cell || !pawn.CanReach(cell, PathEndMode.OnCell, pawn.NormalMaxDanger()))
{
return null;
}
return new Job(JobDefOf.Goto, cell);
}
示例4: GetCoverPositionFrom
private bool GetCoverPositionFrom(Pawn pawn, IntVec3 fromPosition, float maxDist, out IntVec3 coverPosition)
{
//First check if we have cover already
Vector3 coverVec = (fromPosition - pawn.Position).ToVector3().normalized;
IntVec3 coverCell = (pawn.Position.ToVector3Shifted() + coverVec).ToIntVec3();
Thing cover = coverCell.GetCover();
if (pawn.Position.Standable() && cover != null && !pawn.Position.ContainsStaticFire())
{
coverPosition = pawn.Position;
return true;
}
List<IntVec3> cellList = new List<IntVec3>(GenRadial.RadialCellsAround(pawn.Position, maxDist, true));
IntVec3 nearestPosWithPlantCover = IntVec3.Invalid; //Store the nearest position with plant cover here as a fallback in case we find no hard cover
//Go through each cell in radius around the pawn
foreach (IntVec3 cell in cellList)
{
//Sanity checks
if (cell.IsValid
&& cell.Standable()
&& !Find.PawnDestinationManager.DestinationIsReserved(cell)
&& pawn.CanReach(cell, PathEndMode.ClosestTouch, Danger.Deadly, false)
&& !cell.FireNearby())
{
coverVec = (fromPosition - cell).ToVector3().normalized; //The direction in which we want to have cover
coverCell = (cell.ToVector3Shifted() + coverVec).ToIntVec3(); //The cell we check for cover
cover = coverCell.GetCover();
if (cover != null)
{
//If the cover is a plant we store the location for later
if (cover.def.category == ThingCategory.Plant && nearestPosWithPlantCover == IntVec3.Invalid)
{
nearestPosWithPlantCover = cell;
}
//The cell has hard cover in the direction we want, so we return the cell and report success
else
{
coverPosition = cell;
return true;
}
}
}
}
//No hard cover to move up to, use nearest plant cover instead and report success
if (nearestPosWithPlantCover.IsValid)
{
coverPosition = nearestPosWithPlantCover;
return true;
}
//No hard nor plant cover in the radius, report failure
coverPosition = IntVec3.Invalid;
return false;
}
示例5: PotentialWorkCellsGlobal
// Note: this function must be overriden as the one in WorkGiver_Grower class only takes into account colony's hydroponics basins.
// Growing zone are not managed though!
public override IEnumerable<IntVec3> PotentialWorkCellsGlobal(Pawn pawn)
{
List<IntVec3> workCells = new List<IntVec3>();
List<Thing> hydroponicsList = Find.ListerThings.ThingsOfDef(ThingDef.Named("HydroponicsBasin"));
for (int plantGrowerIndex = 0; plantGrowerIndex < hydroponicsList.Count; plantGrowerIndex++)
{
Thing potentialPlantGrower = hydroponicsList[plantGrowerIndex];
if ((potentialPlantGrower.Faction != null)
&& (potentialPlantGrower.Faction == OG_Util.FactionOfMiningCo))
{
Building_PlantGrower plantGrower = potentialPlantGrower as Building_PlantGrower;
if (plantGrower == null)
{
Log.Warning("WorkGiver_GrowerOutpost: found a thing of def HydroponicsBasin or PlantPot which is not a Building_PlantGrower.");
continue;
}
if (GenPlant.GrowthSeasonNow(plantGrower.Position) == false)
{
continue;
}
if (this.ExtraRequirements(plantGrower) == false)
{
continue;
}
if (plantGrower.IsForbidden(pawn))
{
continue;
}
if (pawn.CanReach(plantGrower, PathEndMode.OnCell, pawn.NormalMaxDanger(), false) == false)
{
continue;
}
if (plantGrower.IsBurning())
{
continue;
}
base.DetermineWantedPlantDef(plantGrower.Position);
if (WorkGiver_Grower.wantedPlantDef == null)
{
continue;
}
foreach (IntVec3 cell in plantGrower.OccupiedRect().Cells)
{
workCells.Add(cell);
}
}
}
return workCells;
}
示例6: TryGiveTerminalJob
protected override Job TryGiveTerminalJob(Pawn pawn)
{
JobDef huntJobDef = Animals_AI.GetHuntForAnimalsJobDef();
if ((pawn.jobs.curJob == null) || ((pawn.jobs.curJob.def != huntJobDef) && pawn.jobs.curJob.checkOverrideOnExpire))
{
Pawn targetA = null;
IEnumerator<Pawn> enumerator = HerdAIUtility_Pets.FindHerdMembers(pawn).GetEnumerator();
try
{
while (enumerator.MoveNext())
{
Pawn current = enumerator.Current;
if (!current.Downed
&& (current.jobs.curJob != null)
&& (current.jobs.curJob.def == huntJobDef))
{
TargetInfo huntTarget = current.jobs.curJob.targetA;
if ((huntTarget != null)
&& pawn.CanReach(huntTarget, PathEndMode.OnCell, Danger.Deadly)
&& !(huntTarget.Thing is Corpse)
&& !((Pawn)huntTarget).Dead
&& (pawn.Position - huntTarget.Center).LengthHorizontalSquared <= HUNT_DISTANCE)
{
targetA = (Pawn)huntTarget;
if (targetA != null)
{
return new Job(huntJobDef)
{
targetA = targetA,
maxNumMeleeAttacks = 4,
killIncappedTarget = true,
checkOverrideOnExpire = true,
expiryInterval = 500
};
}
}
}
}
}
finally
{
enumerator.Dispose();
}
}
return null;
}
示例7: GetFloatMenuOptions
public override IEnumerable<FloatMenuOption> GetFloatMenuOptions(Pawn myPawn)
{
List<FloatMenuOption> list = new List<FloatMenuOption>();
{
if (!myPawn.CanReserve(this, 1))
{
FloatMenuOption item = new FloatMenuOption("CannotUseReserved", null);
return new List<FloatMenuOption>
{
item
};
}
if (!myPawn.CanReach(this, PathEndMode.Touch, Danger.Some))
{
FloatMenuOption item2 = new FloatMenuOption("CannotUseNoPath", null);
return new List<FloatMenuOption>
{
item2
};
}
Action action3 = delegate
{
Job job = new Job(DefDatabase<JobDef>.GetNamed("ClutterGoAndPickUpItem", true), this, this.Position);
myPawn.drafter.TakeOrderedJob(job);
OwnerPawn = myPawn;
};
list.Add(new FloatMenuOption("Pick Up" + this.def.LabelCap, action3));
Action action2 = delegate
{
Job job = new Job(DefDatabase<JobDef>.GetNamed("ClutterUseItem", true), this, this.Position);
myPawn.drafter.TakeOrderedJob(job);
OwnerPawn = myPawn;
};
list.Add(new FloatMenuOption("Use" + this.def.LabelCap, action2));
}
return list;
}
示例8: GetFloatMenuOptions
public override IEnumerable<FloatMenuOption> GetFloatMenuOptions(Pawn myPawn)
{
List<FloatMenuOption> list = new List<FloatMenuOption>();
{
if (!myPawn.CanReserve(this))
{
FloatMenuOption item = new FloatMenuOption("CannotUseReserved", null);
return new List<FloatMenuOption>
{
item
};
}
if (!myPawn.CanReach(this, PathEndMode.Touch, Danger.Some))
{
FloatMenuOption item2 = new FloatMenuOption("CannotUseNoPath", null);
return new List<FloatMenuOption>
{
item2
};
}
if (OwnerPawn == null)
{
Action action = delegate
{
job1 = new Job(JobDefOf.Goto, this.InteractionCell);
job2 = new Job(JobDefOf.Wait, 18100);
myPawn.drafter.TakeOrderedJob(job1);
myPawn.drafter.pawn.QueueJob(job2);
JobPawn = myPawn;
myPawn.Reserve(this);
};
list.Add(new FloatMenuOption("Use Dermal Regenerator", action));
}
}
return list;
}
示例9: GetFloatMenuOptions
public override IEnumerable<FloatMenuOption> GetFloatMenuOptions(Pawn myPawn)
{
List<FloatMenuOption> list = new List<FloatMenuOption>();
{
if (!myPawn.CanReserve(this, 1))
{
FloatMenuOption item = new FloatMenuOption("CannotUseReserved", null);
return new List<FloatMenuOption>
{
item
};
}
if (!myPawn.CanReach(this, PathEndMode.Touch, Danger.Some))
{
FloatMenuOption item2 = new FloatMenuOption("CannotUseNoPath", null);
return new List<FloatMenuOption>
{
item2
};
}
Action action1 = delegate
{
Job job = new Job(JobDefOf.Goto, this);
myPawn.QueueJob(job);
myPawn.jobs.StopAll();
MainDealer = myPawn;
ActiveUse = true;
};
list.Add(new FloatMenuOption("Use Pills", action1));
Action action = delegate
{
Job job = new Job(DefDatabase<JobDef>.GetNamed("ClutterGoAndPickUpItem", true), this, this.Position);
Job job1 = new Job(DefDatabase<JobDef>.GetNamed("JobDriver_SleepPills", true), this, myPawn.CurrentBed());
myPawn.QueueJob(job);
myPawn.QueueJob(job1);
MainDealer = myPawn;
ActivePickUp = true;
};
list.Add(new FloatMenuOption("Pick Up", action));
if (this.stackCount > 1)
{
Action action3 = delegate
{
Job job = new Job(DefDatabase<JobDef>.GetNamed("ClutterGoAndPickUpItem", true), this, this.Position);
myPawn.QueueJob(job);
myPawn.jobs.StopAll();
MainDealer = myPawn;
ActivePickOne = true;
ActivePickUp = true;
};
list.Add(new FloatMenuOption("Pick Up One Pill", action3));
}
}
return list;
}
示例10: GetFloatMenuOptions
public override IEnumerable<FloatMenuOption> GetFloatMenuOptions(Pawn myPawn)
{
List<FloatMenuOption> list = new List<FloatMenuOption>();
{
if (!myPawn.CanReserve(this, 1))
{
FloatMenuOption item = new FloatMenuOption("CannotUseReserved", null);
return new List<FloatMenuOption>
{
item
};
}
if (!myPawn.CanReach(this, PathEndMode.Touch, Danger.Some))
{
FloatMenuOption item2 = new FloatMenuOption("CannotUseNoPath", null);
return new List<FloatMenuOption>
{
item2
};
}
if (Find.MapConditionManager.ConditionIsActive(MapConditionDefOf.SolarFlare))
{
FloatMenuOption item3 = new FloatMenuOption("CannotUseSolarFlare".Translate(), null);
return new List<FloatMenuOption>
{
item3
};
}
if (!this.powerComp.PowerOn)
{
FloatMenuOption item4 = new FloatMenuOption("CannotUseNoPower".Translate(), null);
return new List<FloatMenuOption>
{
item4
};
}
if (!Find.ResearchManager.IsFinished(ResearchProjectDef.Named("ColoredLights")))
{
FloatMenuOption item5 = new FloatMenuOption("NeedsResearch".Translate(), null);
return new List<FloatMenuOption>
{
item5
};
}
if (!YellowLight)
{
Action action1 = delegate
{
Job job = new Job(JobDefOf.Goto, this);
myPawn.QueueJob(job);
myPawn.jobs.StopAll();
LampNumber = 1;
pawn = myPawn; ;
jobPawn = job;
};
list.Add(new FloatMenuOption("Yellow Light", action1));
}
if (!BlueLight)
{
Action action2 = delegate
{
Job job = new Job(JobDefOf.Goto, this);
myPawn.QueueJob(job);
myPawn.jobs.StopAll();
LampNumber = 2;
pawn = myPawn;
jobPawn = job;
};
list.Add(new FloatMenuOption("Blue Light", action2));
}
if (!RedLight)
{
Action action3 = delegate
{
Job job = new Job(JobDefOf.Goto, this);
myPawn.QueueJob(job);
myPawn.jobs.StopAll();
LampNumber = 3;
pawn = myPawn;
jobPawn = job;
};
list.Add(new FloatMenuOption("Red Light", action3));
}
if (!GreenLight)
{
Action action4 = delegate
{
//.........这里部分代码省略.........
示例11: GetFloatMenuOptions
public override IEnumerable<FloatMenuOption> GetFloatMenuOptions(Pawn pawn)
{
List<FloatMenuOption> list = new List<FloatMenuOption>();
if (pawn.Dead
|| pawn.Downed
|| pawn.IsBurning())
{
FloatMenuOption item = new FloatMenuOption("Cannot use (incapacitated)", null);
yield return item;
yield break;
}
if (pawn.CanReserve(this) == false)
{
FloatMenuOption item = new FloatMenuOption("Cannot use (reserved)", null);
yield return item;
yield break;
}
else if (pawn.CanReach(this, PathEndMode.ClosestTouch, Danger.Some) == false)
{
FloatMenuOption item = new FloatMenuOption("Cannot use (no path)", null);
yield return item;
yield break;
}
else
{
switch (this.reverseEngineeringState)
{
case ReverseEngineeringState.BuildingNotApproched:
Action action = delegate
{
Job job = new Job(DefDatabase<JobDef>.GetNamed(Util_MechanoidTerraformer.JobDefName_ScoutStrangeArtifact), this);
pawn.drafter.TakeOrderedJob(job);
};
FloatMenuOption item = new FloatMenuOption("Scout strange artifact", action);
yield return item;
break;
case ReverseEngineeringState.BuildingNotSecured:
Action action2 = delegate
{
Job job = new Job(DefDatabase<JobDef>.GetNamed(Util_MechanoidTerraformer.JobDefName_SecureStrangeArtifact), this);
pawn.drafter.TakeOrderedJob(job);
};
FloatMenuOption item2 = new FloatMenuOption("Secure strange artifact", action2);
yield return item2;
break;
case ReverseEngineeringState.Studying:
if (pawn.drafter.Drafted)
{
yield break;
}
if (this.studyIsPaused)
{
Action action3 = delegate
{
this.studyIsPaused = false;
if ((pawn.skills.GetSkill(SkillDefOf.Research).TotallyDisabled == false)
&& (pawn.skills.GetSkill(SkillDefOf.Research).level >= minResearchLevelToStudyArtifact))
{
Job job = new Job(DefDatabase<JobDef>.GetNamed(Util_MechanoidTerraformer.JobDefName_StudyStrangeArtifact), this);
pawn.drafter.TakeOrderedJob(job);
}
else
{
Messages.Message(pawn.Name.ToStringShort + " is not skilled enough to study the strange artifact (research level " + minResearchLevelToStudyArtifact + " is required).", MessageSound.RejectInput);
pawn.jobs.StopAll(true);
}
};
FloatMenuOption item3 = new FloatMenuOption("Start study", action3);
yield return item3;
}
else
{
Action action4 = delegate
{
this.studyIsPaused = true;
pawn.jobs.StopAll(true);
};
FloatMenuOption item4 = new FloatMenuOption("Pause study", action4);
yield return item4;
}
break;
case ReverseEngineeringState.StudyCompleted:
if (pawn.drafter.Drafted)
{
yield break;
}
Action action5 = delegate
{
this.reroutingIsPaused = false;
this.reverseEngineeringState = ReverseEngineeringState.ReroutingPower;
if ((pawn.skills.GetSkill(SkillDefOf.Research).TotallyDisabled == false)
&& (pawn.skills.GetSkill(SkillDefOf.Research).level >= minResearchLevelToReroutePower))
{
Job job = new Job(DefDatabase<JobDef>.GetNamed(Util_MechanoidTerraformer.JobDefName_ReroutePower), this);
pawn.drafter.TakeOrderedJob(job);
//.........这里部分代码省略.........
示例12: JobOnThing
public override Job JobOnThing(Pawn pawn, Thing researchBench)
{
var billGiver = researchBench as IBillGiver;
Bill bill;
// check if can generate bills
if (billGiver == null)
{
return null;
}
// require no power or power available
if (!billGiver.CurrentlyUsable())
{
return null;
}
if (!pawn.CanReserve(researchBench) ||
!pawn.CanReach(researchBench.InteractionCell, PathEndMode.OnCell, Danger.Some) ||
researchBench.IsBurning() || researchBench.IsForbidden(pawn))
{
return null;
}
// researchBench has added bills
if (billGiver.BillStack.Count == 1)
{
// clear bill stack if research is finished or changed
if (billGiver.BillStack[0].recipe.defName != Find.ResearchManager.currentProj.defName ||
ResearchProjectDef.Named(billGiver.BillStack[0].recipe.defName).IsFinished)
{
billGiver.BillStack.Clear();
}
}
// Add research bill if it's not added already
if (billGiver.BillStack.Count == 0)
{
bill = new Bill_Production(DefDatabase<RecipeDef>.GetNamed(Find.ResearchManager.currentProj.defName))
{
suspended = true
};
// NOTE: why suspended???
billGiver.BillStack.AddBill(bill);
}
else
{
bill = billGiver.BillStack[0];
}
if (!TryFindBestBillIngredients(bill, pawn, researchBench, chosenIngridiens))
{
if (FloatMenuMakerMap.making)
{
JobFailReason.Is(MissingMaterialsTranslated);
}
return null;
}
bill.suspended = false;
// clear the work table
var haulAside = WorkGiverUtility.HaulStuffOffBillGiverJob(pawn, billGiver, null);
if (haulAside != null)
{
return haulAside;
}
// gather ingridients and do bill
var doBill = new Job(JobDefOf.Research, researchBench)
{
targetQueueB = new List<TargetInfo>(chosenIngridiens.Count),
numToBringList = new List<int>(chosenIngridiens.Count)
};
foreach (var ingridient in chosenIngridiens)
{
doBill.targetQueueB.Add(ingridient.thing);
doBill.numToBringList.Add(ingridient.count);
}
doBill.haulMode = HaulMode.ToCellNonStorage;
doBill.bill = bill;
return doBill;
}
示例13: GetFloatMenuOptions
public override IEnumerable<FloatMenuOption> GetFloatMenuOptions(Pawn myPawn)
{
List<FloatMenuOption> list = new List<FloatMenuOption>();
{
if (!myPawn.CanReserve(this, 1))
{
FloatMenuOption item = new FloatMenuOption("CannotUseReserved", null);
return new List<FloatMenuOption> { item };
}
if (!myPawn.CanReach(this, PathEndMode.Touch, Danger.Some))
{
FloatMenuOption item2 = new FloatMenuOption("CannotUseNoPath", null);
return new List<FloatMenuOption> { item2 };
}
}
return list;
}
示例14: GetFloatMenuOptions
public override IEnumerable<FloatMenuOption> GetFloatMenuOptions(Pawn myPawn)
{
if (this.Faction == Faction.OfPlayer)
{
return base.GetFloatMenuOptions(myPawn);
}
else
{
List<FloatMenuOption> list = new List<FloatMenuOption>();
CompPowerTrader powerComp = this.TryGetComp<CompPowerTrader>();
if (myPawn.Dead
|| myPawn.Downed
|| myPawn.IsBurning())
{
FloatMenuOption item = new FloatMenuOption("Cannot use (incapacitated)", null);
list.Add(item);
}
if (myPawn.CanReserve(this) == false)
{
FloatMenuOption item = new FloatMenuOption("Cannot use (reserved)", null);
list.Add(item);
}
else if (myPawn.CanReach(this, PathEndMode.ClosestTouch, Danger.Some) == false)
{
FloatMenuOption item = new FloatMenuOption("Cannot use (no path)", null);
list.Add(item);
}
else if (this.IsBurning())
{
FloatMenuOption item = new FloatMenuOption("Cannot use (burning)", null);
list.Add(item);
}
else if (powerComp.PowerOn == false)
{
FloatMenuOption item = new FloatMenuOption("Cannot use (no power)", null);
list.Add(item);
}
else
{
Action action = delegate
{
Job job = new Job(DefDatabase<JobDef>.GetNamed(OG_Util.JobDefName_TryToCaptureOutpost), this);
myPawn.drafter.TakeOrderedJob(job);
};
FloatMenuOption item2 = new FloatMenuOption("Try to capture outpost", action);
list.Add(item2);
}
return list;
}
}
示例15: TryGiveTerminalJob
protected override Job TryGiveTerminalJob(Pawn pawn)
{
if (Find.TickManager.TicksGame - pawn.mindState.lastDisturbanceTick < 400)
{
return null;
}
// find your own bed
Building_Bed catbed = RestUtility.FindBedFor(pawn);
// sleep in your own bed 3/4 of the time
if (catbed != null && Rand.Range(0f, 1f) > .75f)
{
return new Job(JobDefOf.LayDown, catbed);
}
// sleep in owners bed 1/3 of the remainder
if (Rand.Range(0f, 1f) > .33f && pawn.playerSettings.master != null)
{
Building_Bed masterbed = pawn.playerSettings.master.ownership.OwnedBed;
if (masterbed != null)
{
List<IntVec3> bedcells = masterbed.OccupiedRect().Cells.ToList();
bedcells.Remove(masterbed.Position);
return new Job(JobDefOf.LayDown, bedcells.RandomElement());
}
}
// find all non-prisoner, non-medical beds
IEnumerable<Building_Bed> pawnbeds = from b in Find.ListerBuildings.AllBuildingsColonistOfClass<Building_Bed>()
where !b.ForPrisoners && !b.Medical && pawn.CanReach(b.Position, PathEndMode.OnCell, Danger.Some)
select b;
// find all buildings labeled as having a surface, specifically exclude core stove
IEnumerable<Building> surfaces = from t in Find.ListerBuildings.allBuildingsColonist as List<Building>
where t.def.surfaceType != SurfaceType.None
&& pawn.CanReach(t.Position, PathEndMode.OnCell, Danger.Some)
&& t.def.defName != "CookStove"
select t;
// try to sleep on beds that occupy more than one space, and don't already have a cat on them.
// if two cats decide to sleep on the same spot, they will sleep on top of eachother, but I'm going to call that a feature.
// they also probably don't get restefficiency bonuses from better beds, but I'm not sure cats ever do.
if (pawnbeds != null && pawnbeds.Any())
{
// all cells in all non-prisoner, non-medical beds and all surfaces
IEnumerable<IntVec3> bedcells = pawnbeds.SelectMany(b => b.OccupiedRect().Cells);
IEnumerable<IntVec3> surfacecells = surfaces.SelectMany(t => t.OccupiedRect().Cells);
IEnumerable<IntVec3> cells = bedcells.Union(surfacecells);
// all cells that will be occupied by colonists (beds only)
IEnumerable<IntVec3> pawnspots = pawnbeds.Select(b => b.Position);
// all bed cells that will not be occupied by colonists
IEnumerable<IntVec3> catspots = cells.Except(pawnspots);
// reachable, and not already occupied
IEnumerable<IntVec3> viable = from c in catspots
where pawn.CanReach(c, PathEndMode.OnCell, Danger.Some)
&& c.GetFirstThing(ThingDef.Named("Fluffy_DomesticCat")) == null
select c;
if (viable != null && viable.Any())
{
return new Job(JobDefOf.LayDown, viable.RandomElement());
}
}
// sleep on floor as last resort
IntVec3 vec = CellFinder.RandomClosewalkCellNear(pawn.Position, 4);
return new Job(JobDefOf.LayDown, vec);
}