Files
WulaFallenEmpireRW/MCP/vector_cache/Pawn_InventoryTracker-get_FirstUnloadableThing.txt
2025-08-11 21:22:41 +08:00

4149 lines
110 KiB
Plaintext

根据向量相似度分析,与 'get_FirstUnloadableThing, Pawn_InventoryTracker' 最相关的代码定义如下:
---
**文件路径 (精确匹配):** `C:\Steam\steamapps\common\RimWorld\Data\dll1.6\Verse\Pawn_InventoryTracker.txt`
```csharp
public class Pawn_InventoryTracker : IThingHolder, IExposable
{
public Pawn pawn;
public ThingOwner<Thing> innerContainer;
private bool unloadEverything;
private List<Thing> itemsNotForSale = new List<Thing>();
private List<Thing> unpackedCaravanItems = new List<Thing>();
public static readonly Texture2D DrugTex = ContentFinder<Texture2D>.Get("UI/Commands/TakeDrug");
private static List<ThingDefCount> tmpItemsToKeep = new List<ThingDefCount>();
private static readonly List<Thing> tmpThingList = new List<Thing>();
private List<Thing> usableDrugsTmp = new List<Thing>();
public bool UnloadEverything
{
get
{
if (unloadEverything)
{
return HasAnyUnloadableThing;
}
return false;
}
set
{
if (value && HasAnyUnloadableThing)
{
unloadEverything = true;
}
else
{
unloadEverything = false;
}
}
}
public bool HasAnyUnpackedCaravanItems => unpackedCaravanItems.Count > 0;
private bool HasAnyUnloadableThing => FirstUnloadableThing != default(ThingCount);
public ThingCount FirstUnloadableThing
{
get
{
if (innerContainer.Count == 0)
{
return default(ThingCount);
}
if (pawn.drugs?.CurrentPolicy != null)
{
DrugPolicy currentPolicy = pawn.drugs.CurrentPolicy;
tmpItemsToKeep.Clear();
for (int i = 0; i < currentPolicy.Count; i++)
{
if (currentPolicy[i].takeToInventory > 0)
{
tmpItemsToKeep.Add(new ThingDefCount(currentPolicy[i].drug, currentPolicy[i].takeToInventory));
}
}
}
Pawn_InventoryStockTracker inventoryStock = pawn.inventoryStock;
if (inventoryStock != null && inventoryStock.stockEntries?.Count > 0)
{
foreach (InventoryStockEntry value in pawn.inventoryStock.stockEntries.Values)
{
tmpItemsToKeep.Add(new ThingDefCount(value.thingDef, value.count));
}
}
foreach (Thing item in innerContainer)
{
int num = -1;
for (int j = 0; j < tmpItemsToKeep.Count; j++)
{
if (item.def == tmpItemsToKeep[j].ThingDef)
{
num = j;
break;
}
}
if (pawn.IsColonist && item.def.IsNutritionGivingIngestible && !item.def.IsDrug && JobGiver_PackFood.IsGoodPackableFoodFor(item, pawn, checkMass: false))
{
float inventoryPackableFoodNutrition = JobGiver_PackFood.GetInventoryPackableFoodNutrition(pawn);
float maxLevel = pawn.needs.food.MaxLevel;
if (inventoryPackableFoodNutrition - item.GetStatValue(StatDefOf.Nutrition) * (float)item.stackCount <= maxLevel)
{
int k;
for (k = 0; inventoryPackableFoodNutrition - item.GetStatValue(StatDefOf.Nutrition) * (float)k > maxLevel; k++)
{
}
if (item.stackCount - k > 0)
{
tmpItemsToKeep.Add(new ThingDefCount(item.def, item.stackCount - k));
num = tmpItemsToKeep.Count - 1;
}
}
}
if (num < 0)
{
return new ThingCount(item, item.stackCount);
}
if (item.stackCount > tmpItemsToKeep[num].Count)
{
return new ThingCount(item, item.stackCount - tmpItemsToKeep[num].Count);
}
tmpItemsToKeep[num] = new ThingDefCount(tmpItemsToKeep[num].ThingDef, tmpItemsToKeep[num].Count - item.stackCount);
}
return default(ThingCount);
}
}
public IThingHolder ParentHolder => pawn;
public Pawn_InventoryTracker(Pawn pawn)
{
this.pawn = pawn;
innerContainer = new ThingOwner<Thing>(this, oneStackOnly: false);
}
public void ExposeData()
{
Scribe_Collections.Look(ref itemsNotForSale, "itemsNotForSale", LookMode.Reference);
Scribe_Collections.Look(ref unpackedCaravanItems, "unpackedCaravanItems", LookMode.Reference);
Scribe_Deep.Look(ref innerContainer, "innerContainer", this);
Scribe_Values.Look(ref unloadEverything, "unloadEverything", defaultValue: false);
}
public void InventoryTrackerTick()
{
if (unloadEverything && !HasAnyUnloadableThing)
{
unloadEverything = false;
}
}
public void DropAllNearPawn(IntVec3 pos, bool forbid = false, bool unforbid = false)
{
DropAllNearPawnHelper(pos, forbid, unforbid);
}
private void DropAllNearPawnHelper(IntVec3 pos, bool forbid = false, bool unforbid = false, bool caravanHaulOnly = false)
{
if (pawn.MapHeld == null)
{
Log.Error("Tried to drop all inventory near pawn but the pawn is unspawned. pawn=" + pawn);
return;
}
tmpThingList.Clear();
if (caravanHaulOnly)
{
tmpThingList.AddRange(unpackedCaravanItems);
}
else
{
tmpThingList.AddRange(innerContainer);
}
int i;
for (i = 0; i < tmpThingList.Count; i++)
{
if (caravanHaulOnly && !innerContainer.Contains(tmpThingList[i]))
{
unpackedCaravanItems.Remove(tmpThingList[i]);
Log.Warning("Could not drop unpacked caravan item " + tmpThingList[i].Label + ", inventory no longer contains it");
continue;
}
innerContainer.TryDrop(tmpThingList[i], pos, pawn.MapHeld, ThingPlaceMode.Near, out var _, delegate(Thing t, int unused)
{
if (forbid)
{
t.SetForbiddenIfOutsideHomeArea();
}
if (unforbid)
{
t.SetForbidden(value: false, warnOnFail: false);
}
if (t.def.IsPleasureDrug)
{
LessonAutoActivator.TeachOpportunity(ConceptDefOf.DrugBurning, OpportunityType.Important);
}
LordJob_FormAndSendCaravan lordJob_FormAndSendCaravan = CaravanFormingUtility.GetFormAndSendCaravanLord(pawn)?.LordJob as LordJob_FormAndSendCaravan;
if (caravanHaulOnly && lordJob_FormAndSendCaravan != null && lordJob_FormAndSendCaravan.GatheringItemsNow)
{
CaravanFormingUtility.TryAddItemBackToTransferables(t, lordJob_FormAndSendCaravan.transferables, tmpThingList[i].stackCount);
}
unpackedCaravanItems.Remove(tmpThingList[i]);
});
}
}
public void DropCount(ThingDef def, int count, bool forbid = false, bool unforbid = false)
{
if (pawn.MapHeld == null)
{
Log.Error("Tried to drop a thing near pawn but the pawn is unspawned. pawn=" + pawn);
return;
}
tmpThingList.Clear();
tmpThingList.AddRange(innerContainer);
int num = 0;
for (int i = 0; i < tmpThingList.Count; i++)
{
Thing thing = tmpThingList[i];
if (thing.def != def)
{
continue;
}
int num2 = Math.Min(thing.stackCount, count);
innerContainer.TryDrop(tmpThingList[i], pawn.Position, pawn.MapHeld, ThingPlaceMode.Near, num2, out var _, delegate(Thing t, int unused)
{
if (forbid)
{
t.SetForbiddenIfOutsideHomeArea();
}
if (unforbid)
{
t.SetForbidden(value: false, warnOnFail: false);
}
if (t.def.IsPleasureDrug)
{
LessonAutoActivator.TeachOpportunity(ConceptDefOf.DrugBurning, OpportunityType.Important);
}
});
num += num2;
if (num >= count)
{
break;
}
}
}
public void RemoveCount(ThingDef def, int count, bool destroy = true)
{
tmpThingList.Clear();
tmpThingList.AddRange(innerContainer);
foreach (Thing tmpThing in tmpThingList)
{
if (tmpThing.def != def)
{
continue;
}
if (tmpThing.stackCount > count)
{
tmpThing.stackCount -= count;
break;
}
innerContainer.Remove(tmpThing);
if (destroy)
{
tmpThing.Destroy();
}
break;
}
}
public void DestroyAll(DestroyMode mode = DestroyMode.Vanish)
{
innerContainer.ClearAndDestroyContents(mode);
}
public bool Contains(Thing item)
{
return innerContainer.Contains(item);
}
public int Count(ThingDef def)
{
int num = 0;
foreach (Thing item in innerContainer)
{
if (item.def == def)
{
num += item.stackCount;
}
}
return num;
}
public int Count(Func<Thing, bool> validator)
{
int num = 0;
foreach (Thing item in innerContainer)
{
if (validator(item))
{
num += item.stackCount;
}
}
return num;
}
public void AddHauledCaravanItem(Thing item)
{
if (pawn.carryTracker.innerContainer.TryTransferToContainer(item, innerContainer, item.stackCount, out var resultingTransferredItem, canMergeWithExistingStacks: false) > 0)
{
unpackedCaravanItems.Add(resultingTransferredItem);
}
CompForbiddable compForbiddable = resultingTransferredItem?.TryGetComp<CompForbiddable>();
if (compForbiddable != null)
{
compForbiddable.Forbidden = false;
}
}
public void TryAddAndUnforbid(Thing item)
{
CompForbiddable compForbiddable = item.TryGetComp<CompForbiddable>();
if (innerContainer.TryAdd(item) && compForbiddable != null)
{
compForbiddable.Forbidden = false;
}
}
public void TransferCaravanItemsToCarrier(Pawn_InventoryTracker carrierInventory)
{
List<Thing> list = new List<Thing>();
list.AddRange(pawn.inventory.unpackedCaravanItems);
foreach (Thing item in list)
{
if (MassUtility.IsOverEncumbered(carrierInventory.pawn))
{
break;
}
if (innerContainer.Contains(item))
{
pawn.inventory.innerContainer.TryTransferToContainer(item, carrierInventory.innerContainer, item.stackCount);
}
unpackedCaravanItems.Remove(item);
}
}
public void DropAllPackingCaravanThings()
{
if (pawn.Spawned)
{
DropAllNearPawnHelper(pawn.Position, forbid: false, unforbid: false, caravanHaulOnly: true);
ClearHaulingCaravanCache();
}
}
public void ClearHaulingCaravanCache()
{
unpackedCaravanItems.Clear();
}
public bool NotForSale(Thing item)
{
return itemsNotForSale.Contains(item);
}
public void TryAddItemNotForSale(Thing item)
{
if (innerContainer.TryAdd(item, canMergeWithExistingStacks: false))
{
itemsNotForSale.Add(item);
}
}
public void Notify_ItemRemoved(Thing item)
{
itemsNotForSale.Remove(item);
unpackedCaravanItems.Remove(item);
if (unloadEverything && !HasAnyUnloadableThing)
{
unloadEverything = false;
}
}
public ThingOwner GetDirectlyHeldThings()
{
return innerContainer;
}
public void GetChildHolders(List<IThingHolder> outChildren)
{
ThingOwnerUtility.AppendThingHoldersFromThings(outChildren, GetDirectlyHeldThings());
}
public IEnumerable<Thing> GetDrugs()
{
foreach (Thing item in innerContainer)
{
if (item.TryGetComp<CompDrug>() != null)
{
yield return item;
}
}
}
public IEnumerable<Thing> GetCombatEnhancingDrugs()
{
foreach (Thing item in innerContainer)
{
CompDrug compDrug = item.TryGetComp<CompDrug>();
if (compDrug != null && compDrug.Props.isCombatEnhancingDrug)
{
yield return item;
}
}
}
public Thing FindCombatEnhancingDrug()
{
return GetCombatEnhancingDrugs().FirstOrDefault();
}
public IEnumerable<Gizmo> GetGizmos()
{
if (!pawn.IsColonistPlayerControlled || !pawn.Drafted || Find.Selector.SingleSelectedThing != pawn)
{
yield break;
}
usableDrugsTmp.Clear();
foreach (Thing drug2 in GetDrugs())
{
if (FoodUtility.WillIngestFromInventoryNow(pawn, drug2))
{
usableDrugsTmp.Add(drug2);
}
}
if (usableDrugsTmp.Count == 0)
{
yield break;
}
if (usableDrugsTmp.Count == 1)
{
Thing drug = usableDrugsTmp[0];
string defaultLabel = (drug.def.ingestible.ingestCommandString.NullOrEmpty() ? "ConsumeThing".Translate(drug.LabelNoCount, drug) : drug.def.ingestible.ingestCommandString.Formatted(drug.LabelShort));
Command_Action command_Action = new Command_Action();
command_Action.defaultLabel = defaultLabel;
command_Action.defaultDesc = drug.LabelCapNoCount + ": " + drug.def.description.CapitalizeFirst();
command_Action.icon = drug.def.uiIcon;
command_Action.iconAngle = drug.def.uiIconAngle;
command_Action.iconOffset = drug.def.uiIconOffset;
command_Action.action = delegate
{
FoodUtility.IngestFromInventoryNow(pawn, drug);
};
yield return command_Action;
yield break;
}
Command_Action command_Action2 = new Command_Action();
command_Action2.defaultLabel = "TakeDrug".Translate();
command_Action2.defaultDesc = "TakeDrugDesc".Translate();
command_Action2.icon = DrugTex;
command_Action2.action = delegate
{
List<FloatMenuOption> list = new List<FloatMenuOption>();
foreach (Thing drug in usableDrugsTmp)
{
string label = (drug.def.ingestible.ingestCommandString.NullOrEmpty() ? "ConsumeThing".Translate(drug.LabelNoCount, drug) : drug.def.ingestible.ingestCommandString.Formatted(drug.LabelShort));
list.Add(new FloatMenuOption(label, delegate
{
FoodUtility.IngestFromInventoryNow(pawn, drug);
}));
}
Find.WindowStack.Add(new FloatMenu(list));
};
yield return command_Action2;
}
}
```
---
**文件路径:** `C:\Steam\steamapps\common\RimWorld\Data\dll1.6\Verse\ThingOwnerUtility.txt`
**相似度:** 0.6304
```csharp
public static class ThingOwnerUtility
{
private static readonly Stack<IThingHolder> tmpStack = new Stack<IThingHolder>();
private static readonly List<IThingHolder> tmpHolders = new List<IThingHolder>();
private static readonly List<Thing> tmpThings = new List<Thing>();
private static readonly List<IThingHolder> tmpMapChildHolders = new List<IThingHolder>();
public static bool ThisOrAnyCompIsThingHolder(this ThingDef thingDef)
{
if (typeof(IThingHolder).IsAssignableFrom(thingDef.thingClass))
{
return true;
}
for (int i = 0; i < thingDef.comps.Count; i++)
{
if (typeof(IThingHolder).IsAssignableFrom(thingDef.comps[i].compClass))
{
return true;
}
}
return false;
}
public static ThingOwner TryGetInnerInteractableThingOwner(this Thing thing)
{
IThingHolder thingHolder = thing as IThingHolder;
ThingWithComps thingWithComps = thing as ThingWithComps;
if (thingHolder != null)
{
ThingOwner directlyHeldThings = thingHolder.GetDirectlyHeldThings();
if (directlyHeldThings != null)
{
return directlyHeldThings;
}
}
if (thingWithComps != null)
{
List<ThingComp> allComps = thingWithComps.AllComps;
for (int i = 0; i < allComps.Count; i++)
{
if (allComps[i] is IThingHolder thingHolder2)
{
ThingOwner directlyHeldThings2 = thingHolder2.GetDirectlyHeldThings();
if (directlyHeldThings2 != null)
{
return directlyHeldThings2;
}
}
}
}
tmpHolders.Clear();
if (thingHolder != null)
{
thingHolder.GetChildHolders(tmpHolders);
if (tmpHolders.Any())
{
ThingOwner directlyHeldThings3 = tmpHolders[0].GetDirectlyHeldThings();
if (directlyHeldThings3 != null)
{
tmpHolders.Clear();
return directlyHeldThings3;
}
}
}
if (thingWithComps != null)
{
List<ThingComp> allComps2 = thingWithComps.AllComps;
for (int j = 0; j < allComps2.Count; j++)
{
if (!(allComps2[j] is IThingHolder thingHolder3))
{
continue;
}
thingHolder3.GetChildHolders(tmpHolders);
if (tmpHolders.Any())
{
ThingOwner directlyHeldThings4 = tmpHolders[0].GetDirectlyHeldThings();
if (directlyHeldThings4 != null)
{
tmpHolders.Clear();
return directlyHeldThings4;
}
}
}
}
tmpHolders.Clear();
return null;
}
public static bool SpawnedOrAnyParentSpawned(IThingHolder holder)
{
return SpawnedParentOrMe(holder) != null;
}
public static Thing SpawnedParentOrMe(IThingHolder holder)
{
while (holder != null)
{
if (holder is Thing { Spawned: not false } thing)
{
return thing;
}
if (holder is ThingComp thingComp && thingComp.parent.Spawned)
{
return thingComp.parent;
}
holder = holder.ParentHolder;
}
return null;
}
public static IntVec3 GetRootPosition(IThingHolder holder)
{
IntVec3 result = IntVec3.Invalid;
while (holder != null)
{
if (holder is Thing { Position: { IsValid: not false } } thing)
{
result = thing.Position;
}
else if (holder is ThingComp thingComp && thingComp.parent.Position.IsValid)
{
result = thingComp.parent.Position;
}
holder = holder.ParentHolder;
}
return result;
}
public static Map GetRootMap(IThingHolder holder)
{
while (holder != null)
{
if (holder is Map result)
{
return result;
}
holder = holder.ParentHolder;
}
return null;
}
public static PlanetTile GetRootTile(IThingHolder holder)
{
while (holder != null)
{
if (holder is WorldObject { Tile: { Valid: not false } } worldObject)
{
return worldObject.Tile;
}
holder = holder.ParentHolder;
}
return PlanetTile.Invalid;
}
public static bool ContentsSuspended(IThingHolder holder)
{
while (holder != null)
{
if (holder is Building_CryptosleepCasket || holder is ISuspendableThingHolder { IsContentsSuspended: not false })
{
return true;
}
holder = holder.ParentHolder;
}
return false;
}
public static bool ContentsInCryptosleep(IThingHolder holder)
{
while (holder != null)
{
if (holder is Building_CryptosleepCasket)
{
return true;
}
holder = holder.ParentHolder;
}
return false;
}
public static bool IsEnclosingContainer(this IThingHolder holder)
{
if (holder != null && !(holder is Pawn_CarryTracker) && !(holder is Corpse) && !(holder is Map) && !(holder is Caravan) && !(holder is Settlement_TraderTracker))
{
return !(holder is TradeShip);
}
return false;
}
public static bool ShouldAutoRemoveDestroyedThings(IThingHolder holder)
{
if (!(holder is Corpse))
{
return !(holder is Caravan);
}
return false;
}
public static bool ShouldAutoExtinguishInnerThings(IThingHolder holder)
{
return !(holder is Map);
}
public static bool ShouldRemoveDesignationsOnAddedThings(IThingHolder holder)
{
return holder.IsEnclosingContainer();
}
public static void AppendThingHoldersFromThings(List<IThingHolder> outThingsHolders, IList<Thing> container)
{
if (container == null)
{
return;
}
int i = 0;
for (int count = container.Count; i < count; i++)
{
if (container[i] is IThingHolder item)
{
outThingsHolders.Add(item);
}
if (!(container[i] is ThingWithComps { AllComps: var allComps }))
{
continue;
}
for (int j = 0; j < allComps.Count; j++)
{
if (allComps[j] is IThingHolder item2)
{
outThingsHolders.Add(item2);
}
}
}
}
public static bool AnyParentIs<T>(Thing thing) where T : class, IThingHolder
{
return GetAnyParent<T>(thing) != null;
}
public static T GetAnyParent<T>(Thing thing) where T : class, IThingHolder
{
if (thing is T result)
{
return result;
}
for (IThingHolder parentHolder = thing.ParentHolder; parentHolder != null; parentHolder = parentHolder.ParentHolder)
{
if (parentHolder is T result2)
{
return result2;
}
}
return null;
}
public static Thing GetFirstParentThing(Thing thing)
{
for (IThingHolder parentHolder = thing.ParentHolder; parentHolder != null; parentHolder = parentHolder.ParentHolder)
{
if (parentHolder is Thing result)
{
return result;
}
if (parentHolder is ThingComp thingComp)
{
return thingComp.parent;
}
}
return null;
}
public static Thing GetFirstSpawnedParentThing(Thing thing)
{
if (thing.Spawned)
{
return thing;
}
for (IThingHolder parentHolder = thing.ParentHolder; parentHolder != null; parentHolder = parentHolder.ParentHolder)
{
if (parentHolder is Thing { Spawned: not false } thing2)
{
return thing2;
}
if (parentHolder is ThingComp thingComp && thingComp.parent.Spawned)
{
return thingComp.parent;
}
}
return null;
}
public static void GetAllThingsRecursively(IThingHolder holder, List<Thing> outThings, bool allowUnreal = true, Predicate<IThingHolder> passCheck = null)
{
outThings.Clear();
if (passCheck != null && !passCheck(holder))
{
return;
}
tmpStack.Clear();
tmpStack.Push(holder);
while (tmpStack.Count != 0)
{
IThingHolder thingHolder = tmpStack.Pop();
if (allowUnreal || AreImmediateContentsReal(thingHolder))
{
ThingOwner directlyHeldThings = thingHolder.GetDirectlyHeldThings();
if (directlyHeldThings != null)
{
outThings.AddRange(directlyHeldThings);
}
}
tmpHolders.Clear();
thingHolder.GetChildHolders(tmpHolders);
for (int i = 0; i < tmpHolders.Count; i++)
{
if (passCheck == null || passCheck(tmpHolders[i]))
{
tmpStack.Push(tmpHolders[i]);
}
}
}
tmpStack.Clear();
tmpHolders.Clear();
}
public static void GetAllThingsRecursively<T>(Map map, ThingRequest request, List<T> outThings, bool allowUnreal = true, Predicate<IThingHolder> passCheck = null, bool alsoGetSpawnedThings = true) where T : Thing
{
outThings.Clear();
if (alsoGetSpawnedThings)
{
List<Thing> list = map.listerThings.ThingsMatching(request);
for (int i = 0; i < list.Count; i++)
{
if (list[i] is T item)
{
outThings.Add(item);
}
}
}
tmpMapChildHolders.Clear();
map.GetChildHolders(tmpMapChildHolders);
for (int j = 0; j < tmpMapChildHolders.Count; j++)
{
tmpThings.Clear();
GetAllThingsRecursively(tmpMapChildHolders[j], tmpThings, allowUnreal, passCheck);
for (int k = 0; k < tmpThings.Count; k++)
{
if (tmpThings[k] is T val && request.Accepts(val))
{
outThings.Add(val);
}
}
}
tmpThings.Clear();
tmpMapChildHolders.Clear();
}
public static List<Thing> GetAllThingsRecursively(IThingHolder holder, bool allowUnreal = true)
{
List<Thing> list = new List<Thing>();
GetAllThingsRecursively(holder, list, allowUnreal);
return list;
}
public static bool AreImmediateContentsReal(IThingHolder holder)
{
if (!(holder is Corpse))
{
return !(holder is MinifiedThing);
}
return false;
}
public static bool TryGetFixedTemperature(IThingHolder holder, Thing forThing, out float temperature)
{
if (holder is Pawn_InventoryTracker && forThing.TryGetComp<CompHatcher>() != null)
{
temperature = 14f;
return true;
}
if (holder is CompLaunchable || holder is ActiveTransporterInfo || holder is TravellingTransporters)
{
temperature = 14f;
return true;
}
if (holder is Settlement_TraderTracker || holder is TradeShip)
{
temperature = 14f;
return true;
}
if (holder is CompTransporter)
{
temperature = 14f;
return true;
}
temperature = 21f;
return false;
}
}
```
---
**文件路径:** `C:\Steam\steamapps\common\RimWorld\Data\dll1.6\RimWorld.Planet\CaravanInventoryUtility.txt`
**相似度:** 0.6279
```csharp
public static class CaravanInventoryUtility
{
private static List<Thing> inventoryItems = new List<Thing>();
private static List<Thing> inventoryToMove = new List<Thing>();
private static List<Apparel> tmpApparel = new List<Apparel>();
private static List<ThingWithComps> tmpEquipment = new List<ThingWithComps>();
public static List<Thing> AllInventoryItems(Caravan caravan)
{
inventoryItems.Clear();
List<Pawn> pawnsListForReading = caravan.PawnsListForReading;
for (int i = 0; i < pawnsListForReading.Count; i++)
{
Pawn pawn = pawnsListForReading[i];
for (int num = pawn.inventory.innerContainer.Count - 1; num >= 0; num--)
{
Thing item = pawn.inventory.innerContainer[num];
inventoryItems.Add(item);
}
}
return inventoryItems;
}
public static Building_PassengerShuttle FindShuttle(Caravan caravan)
{
List<Thing> list = AllInventoryItems(caravan);
for (int i = 0; i < list.Count; i++)
{
if (list[i] is Building_PassengerShuttle result)
{
return result;
}
}
return null;
}
public static void CaravanInventoryUtilityStaticUpdate()
{
inventoryItems.Clear();
}
public static Pawn GetOwnerOf(Caravan caravan, Thing item)
{
IThingHolder parentHolder = item.ParentHolder;
if (parentHolder is Pawn_InventoryTracker)
{
Pawn pawn = (Pawn)parentHolder.ParentHolder;
if (caravan.ContainsPawn(pawn))
{
return pawn;
}
}
return null;
}
public static bool TryGetBestFood(Caravan caravan, Pawn forPawn, out Thing food, out Pawn owner)
{
List<Thing> list = AllInventoryItems(caravan);
Thing thing = null;
float num = 0f;
for (int i = 0; i < list.Count; i++)
{
Thing thing2 = list[i];
if (CaravanPawnsNeedsUtility.CanEatForNutritionNow(thing2, forPawn))
{
float foodScore = CaravanPawnsNeedsUtility.GetFoodScore(thing2, forPawn);
if (thing == null || foodScore > num)
{
thing = thing2;
num = foodScore;
}
}
}
if (thing != null)
{
food = thing;
owner = GetOwnerOf(caravan, thing);
return true;
}
food = null;
owner = null;
return false;
}
public static bool TryGetDrugToSatisfyChemicalNeed(Caravan caravan, Pawn forPawn, Hediff hediff, out Thing drug, out Pawn owner)
{
if (hediff == null)
{
drug = null;
owner = null;
return false;
}
List<Thing> list = AllInventoryItems(caravan);
Thing thing = null;
for (int i = 0; i < list.Count; i++)
{
Thing thing2 = list[i];
if (!thing2.IngestibleNow || !thing2.def.IsDrug)
{
continue;
}
CompDrug compDrug = thing2.TryGetComp<CompDrug>();
if (compDrug != null && compDrug.Props.chemical != null && (!(hediff is Hediff_ChemicalDependency hediff_ChemicalDependency) || compDrug.Props.chemical == hediff_ChemicalDependency.chemical) && (!(hediff is Hediff_Addiction hediff_Addiction) || compDrug.Props.chemical.addictionHediff == hediff_Addiction.def))
{
DrugPolicy drugPolicy = forPawn.drugs?.CurrentPolicy;
if (drugPolicy == null || drugPolicy[thing2.def].allowedForAddiction || forPawn.story == null || forPawn.story.traits.DegreeOfTrait(TraitDefOf.DrugDesire) > 0)
{
thing = thing2;
break;
}
}
}
if (thing != null)
{
drug = thing;
owner = GetOwnerOf(caravan, thing);
return true;
}
drug = null;
owner = null;
return false;
}
public static bool TryGetBestMedicine(Caravan caravan, Pawn patient, out Medicine medicine, out Pawn owner)
{
if (patient.playerSettings == null || (int)patient.playerSettings.medCare <= 1)
{
medicine = null;
owner = null;
return false;
}
List<Thing> list = AllInventoryItems(caravan);
Medicine medicine2 = null;
float num = 0f;
for (int i = 0; i < list.Count; i++)
{
Thing thing = list[i];
if (thing.def.IsMedicine && patient.playerSettings.medCare.AllowsMedicine(thing.def))
{
float statValue = thing.GetStatValue(StatDefOf.MedicalPotency);
if (statValue > num || medicine2 == null)
{
num = statValue;
medicine2 = (Medicine)thing;
}
}
}
if (medicine2 != null)
{
medicine = medicine2;
owner = GetOwnerOf(caravan, medicine2);
return true;
}
medicine = null;
owner = null;
return false;
}
public static bool TryGetThingOfDef(Caravan caravan, ThingDef thingDef, out Thing thing, out Pawn owner)
{
List<Thing> list = AllInventoryItems(caravan);
for (int i = 0; i < list.Count; i++)
{
Thing thing2 = list[i];
if (thing2.def == thingDef)
{
thing = thing2;
owner = GetOwnerOf(caravan, thing2);
return true;
}
}
thing = null;
owner = null;
return false;
}
public static void MoveAllInventoryToSomeoneElse(Pawn from, List<Pawn> candidates, List<Pawn> ignoreCandidates = null)
{
inventoryToMove.Clear();
inventoryToMove.AddRange(from.inventory.innerContainer);
for (int i = 0; i < inventoryToMove.Count; i++)
{
MoveInventoryToSomeoneElse(from, inventoryToMove[i], candidates, ignoreCandidates, inventoryToMove[i].stackCount);
}
inventoryToMove.Clear();
}
public static void MoveInventoryToSomeoneElse(Pawn itemOwner, Thing item, List<Pawn> candidates, List<Pawn> ignoreCandidates, int numToMove)
{
if (numToMove < 0 || numToMove > item.stackCount)
{
Log.Warning("Tried to move item " + item?.ToString() + " with numToMove=" + numToMove + " (item stack count = " + item.stackCount + ")");
}
else
{
Pawn pawn = FindPawnToMoveInventoryTo(item, candidates, ignoreCandidates, itemOwner);
if (pawn != null)
{
itemOwner.inventory.innerContainer.TryTransferToContainer(item, pawn.inventory.innerContainer, numToMove);
}
}
}
public static Pawn FindPawnToMoveInventoryTo(Thing item, List<Pawn> candidates, List<Pawn> ignoreCandidates, Pawn currentItemOwner = null)
{
if (item is Pawn)
{
Log.Error("Called FindPawnToMoveInventoryTo but the item is a pawn.");
return null;
}
if (candidates.Where((Pawn x) => CanMoveInventoryTo(x) && (ignoreCandidates == null || !ignoreCandidates.Contains(x)) && x != currentItemOwner && !MassUtility.IsOverEncumbered(x)).TryRandomElement(out var result))
{
return result;
}
if (candidates.Where((Pawn x) => CanMoveInventoryTo(x) && (ignoreCandidates == null || !ignoreCandidates.Contains(x)) && x != currentItemOwner).TryRandomElement(out result))
{
return result;
}
if (candidates.Where((Pawn x) => (ignoreCandidates == null || !ignoreCandidates.Contains(x)) && x != currentItemOwner).TryRandomElement(out result))
{
return result;
}
return null;
}
public static void MoveAllApparelToSomeonesInventory(Pawn moveFrom, List<Pawn> candidates, bool moveLocked = true)
{
if (moveFrom.apparel == null)
{
return;
}
tmpApparel.Clear();
if (moveLocked)
{
tmpApparel.AddRange(moveFrom.apparel.WornApparel);
}
else
{
for (int i = 0; i < moveFrom.apparel.WornApparel.Count; i++)
{
Apparel apparel = moveFrom.apparel.WornApparel[i];
if (!moveFrom.apparel.IsLocked(apparel))
{
tmpApparel.Add(apparel);
}
}
}
for (int j = 0; j < tmpApparel.Count; j++)
{
moveFrom.apparel.Remove(tmpApparel[j]);
FindPawnToMoveInventoryTo(tmpApparel[j], candidates, null, moveFrom)?.inventory.innerContainer.TryAdd(tmpApparel[j]);
}
tmpApparel.Clear();
}
public static void MoveAllEquipmentToSomeonesInventory(Pawn moveFrom, List<Pawn> candidates)
{
if (moveFrom.equipment != null)
{
tmpEquipment.Clear();
tmpEquipment.AddRange(moveFrom.equipment.AllEquipmentListForReading);
for (int i = 0; i < tmpEquipment.Count; i++)
{
moveFrom.equipment.Remove(tmpEquipment[i]);
FindPawnToMoveInventoryTo(tmpEquipment[i], candidates, null, moveFrom)?.inventory.innerContainer.TryAdd(tmpEquipment[i]);
}
tmpEquipment.Clear();
}
}
private static bool CanMoveInventoryTo(Pawn pawn)
{
return MassUtility.CanEverCarryAnything(pawn);
}
public static List<Thing> TakeThings(Caravan caravan, Func<Thing, int> takeQuantity)
{
List<Thing> list = new List<Thing>();
foreach (Thing item in AllInventoryItems(caravan).ToList())
{
int num = takeQuantity(item);
if (num > 0)
{
list.Add(item.holdingOwner.Take(item, num));
}
}
return list;
}
public static void GiveThing(Caravan caravan, Thing thing)
{
if (AllInventoryItems(caravan).Contains(thing))
{
Log.Error("Tried to give the same item twice (" + thing?.ToString() + ") to a caravan (" + caravan?.ToString() + ").");
return;
}
Pawn pawn = FindPawnToMoveInventoryTo(thing, caravan.PawnsListForReading, null);
if (pawn == null)
{
Log.Error($"Failed to give item {thing} to caravan {caravan}; item was lost");
thing.Destroy();
}
else if (!pawn.inventory.innerContainer.TryAdd(thing))
{
Log.Error($"Failed to give item {thing} to caravan {caravan}; item was lost");
thing.Destroy();
}
}
public static bool HasThings(Caravan caravan, ThingDef thingDef, int count, Func<Thing, bool> validator = null)
{
int num = 0;
List<Thing> list = AllInventoryItems(caravan);
for (int i = 0; i < list.Count; i++)
{
Thing thing = list[i];
if (thing.def == thingDef && (validator == null || validator(thing)))
{
num += thing.stackCount;
}
}
return num >= count;
}
public static IEnumerable<Thing> GetAllDissolvingThings(Caravan caravan)
{
ThingRequest group = ThingRequest.ForGroup(ThingRequestGroup.Dissolving);
List<Thing> items = AllInventoryItems(caravan);
for (int i = 0; i < items.Count; i++)
{
if (group.Accepts(items[i]))
{
yield return items[i];
}
}
}
}
```
---
**文件路径:** `C:\Steam\steamapps\common\RimWorld\Data\dll1.6\Verse\ThingOwner.txt`
**相似度:** 0.6188
```csharp
public abstract class ThingOwner : IExposable, IList<Thing>, ICollection<Thing>, IEnumerable<Thing>, IEnumerable
{
protected IThingHolder owner;
protected int maxStacks = 999999;
public LookMode contentsLookMode = LookMode.Deep;
public bool removeContentsIfDestroyed = true;
private const int InfMaxStacks = 999999;
public IThingHolder Owner => owner;
public abstract int Count { get; }
public Thing this[int index] => GetAt(index);
public bool Any => Count > 0;
public int TotalStackCount
{
get
{
int num = 0;
int count = Count;
for (int i = 0; i < count; i++)
{
num += GetAt(i).stackCount;
}
return num;
}
}
public string ContentsString
{
get
{
if (Any)
{
return GenThing.ThingsToCommaList(this);
}
return "NothingLower".Translate();
}
}
Thing IList<Thing>.this[int index]
{
get
{
return GetAt(index);
}
set
{
throw new InvalidOperationException("ThingOwner doesn't allow setting individual elements.");
}
}
bool ICollection<Thing>.IsReadOnly => true;
public event Action OnContentsChanged;
public ThingOwner()
{
}
public ThingOwner(IThingHolder owner)
{
this.owner = owner;
}
public ThingOwner(IThingHolder owner, LookMode contentsLookMode = LookMode.Deep, bool removeContentsIfDestroyed = true)
{
this.owner = owner;
this.contentsLookMode = contentsLookMode;
this.removeContentsIfDestroyed = removeContentsIfDestroyed;
}
public ThingOwner(IThingHolder owner, bool oneStackOnly, LookMode contentsLookMode = LookMode.Deep, bool removeContentsIfDestroyed = true)
: this(owner)
{
maxStacks = (oneStackOnly ? 1 : 999999);
this.contentsLookMode = contentsLookMode;
this.removeContentsIfDestroyed = removeContentsIfDestroyed;
}
public virtual void ExposeData()
{
Scribe_Values.Look(ref maxStacks, "maxStacks", 999999);
Scribe_Values.Look(ref contentsLookMode, "contentsLookMode", LookMode.Deep);
Scribe_Values.Look(ref removeContentsIfDestroyed, "removeContentsIfDestroyed", defaultValue: true);
}
public void DoTick()
{
for (int num = Count - 1; num >= 0; num--)
{
Thing at = GetAt(num);
int offset = ((owner is Thing t) ? t.HashOffset() : 0);
at.DoTick();
if (at.def.tickerType == TickerType.Rare && GenTicks.IsTickInterval(offset, 250))
{
at.TickRare();
}
else if (at.def.tickerType == TickerType.Long && GenTicks.IsTickInterval(offset, 2000))
{
at.TickLong();
}
if (at.Destroyed && removeContentsIfDestroyed)
{
Remove(at);
}
}
}
public void Clear()
{
for (int num = Count - 1; num >= 0; num--)
{
Remove(GetAt(num));
}
}
public void ClearAndDestroyContents(DestroyMode mode = DestroyMode.Vanish)
{
while (Any)
{
for (int num = Count - 1; num >= 0; num--)
{
Thing at = GetAt(num);
at.Destroy(mode);
Remove(at);
}
}
}
public void ClearAndDestroyContentsOrPassToWorld(DestroyMode mode = DestroyMode.Vanish)
{
while (Any)
{
for (int num = Count - 1; num >= 0; num--)
{
Thing at = GetAt(num);
at.DestroyOrPassToWorld(mode);
Remove(at);
}
}
}
public bool CanAcceptAnyOf(Thing item, bool canMergeWithExistingStacks = true)
{
return GetCountCanAccept(item, canMergeWithExistingStacks) > 0;
}
public virtual int GetCountCanAccept(Thing item, bool canMergeWithExistingStacks = true)
{
if (item == null || item.stackCount <= 0)
{
return 0;
}
if (maxStacks == 999999)
{
return item.stackCount;
}
int num = 0;
if (Count < maxStacks)
{
num += (maxStacks - Count) * item.def.stackLimit;
}
if (num >= item.stackCount)
{
return Mathf.Min(num, item.stackCount);
}
if (canMergeWithExistingStacks)
{
int i = 0;
for (int count = Count; i < count; i++)
{
Thing at = GetAt(i);
if (at.stackCount < at.def.stackLimit && at.CanStackWith(item))
{
num += at.def.stackLimit - at.stackCount;
if (num >= item.stackCount)
{
return Mathf.Min(num, item.stackCount);
}
}
}
}
return Mathf.Min(num, item.stackCount);
}
public abstract int TryAdd(Thing item, int count, bool canMergeWithExistingStacks = true);
public abstract bool TryAdd(Thing item, bool canMergeWithExistingStacks = true);
public abstract int IndexOf(Thing item);
public abstract bool Remove(Thing item);
protected abstract Thing GetAt(int index);
public bool Contains(Thing item)
{
if (item == null)
{
return false;
}
return item.holdingOwner == this;
}
public void RemoveAt(int index)
{
if (index < 0 || index >= Count)
{
throw new ArgumentOutOfRangeException("index");
}
Remove(GetAt(index));
}
public int TryAddOrTransfer(Thing item, int count, bool canMergeWithExistingStacks = true)
{
if (item == null)
{
Log.Warning("Tried to add or transfer null item to ThingOwner.");
return 0;
}
if (item.holdingOwner != null)
{
return item.holdingOwner.TryTransferToContainer(item, this, count, canMergeWithExistingStacks);
}
return TryAdd(item, count, canMergeWithExistingStacks);
}
public bool TryAddOrTransfer(Thing item, bool canMergeWithExistingStacks = true)
{
if (item == null)
{
Log.Warning("Tried to add or transfer null item to ThingOwner.");
return false;
}
if (item.holdingOwner != null)
{
return item.holdingOwner.TryTransferToContainer(item, this, canMergeWithExistingStacks);
}
return TryAdd(item, canMergeWithExistingStacks);
}
public void TryAddRangeOrTransfer(IEnumerable<Thing> things, bool canMergeWithExistingStacks = true, bool destroyLeftover = false)
{
if (things == this)
{
return;
}
if (things is ThingOwner thingOwner)
{
thingOwner.TryTransferAllToContainer(this, canMergeWithExistingStacks);
if (destroyLeftover)
{
thingOwner.ClearAndDestroyContents();
}
return;
}
if (things is IList<Thing> list)
{
for (int i = 0; i < list.Count; i++)
{
if (!TryAddOrTransfer(list[i], canMergeWithExistingStacks) && destroyLeftover)
{
list[i].Destroy();
}
}
return;
}
foreach (Thing thing in things)
{
if (!TryAddOrTransfer(thing, canMergeWithExistingStacks) && destroyLeftover)
{
thing.Destroy();
}
}
}
public int RemoveAll(Predicate<Thing> predicate)
{
int num = 0;
for (int num2 = Count - 1; num2 >= 0; num2--)
{
if (predicate(GetAt(num2)))
{
Remove(GetAt(num2));
num++;
}
}
return num;
}
public bool TryTransferToContainer(Thing item, ThingOwner otherContainer, bool canMergeWithExistingStacks = true)
{
return TryTransferToContainer(item, otherContainer, item.stackCount, canMergeWithExistingStacks) == item.stackCount;
}
public int TryTransferToContainer(Thing item, ThingOwner otherContainer, int count, bool canMergeWithExistingStacks = true)
{
Thing resultingTransferredItem;
return TryTransferToContainer(item, otherContainer, count, out resultingTransferredItem, canMergeWithExistingStacks);
}
public int TryTransferToContainer(Thing item, ThingOwner otherContainer, int count, out Thing resultingTransferredItem, bool canMergeWithExistingStacks = true)
{
if (!Contains(item))
{
Log.Error("Can't transfer item " + item?.ToString() + " because it's not here. owner=" + owner.ToStringSafe());
resultingTransferredItem = null;
return 0;
}
if (otherContainer == this && count > 0)
{
resultingTransferredItem = item;
return item.stackCount;
}
if (!otherContainer.CanAcceptAnyOf(item, canMergeWithExistingStacks))
{
resultingTransferredItem = null;
return 0;
}
if (count <= 0)
{
resultingTransferredItem = null;
return 0;
}
if (owner is Map || otherContainer.owner is Map)
{
Log.Warning("Can't transfer items to or from Maps directly. They must be spawned or despawned manually. Use TryAdd(item.SplitOff(count))");
resultingTransferredItem = null;
return 0;
}
int num = Mathf.Min(item.stackCount, count);
Thing thing = item.SplitOff(num);
if (Contains(thing))
{
Remove(thing);
}
if (otherContainer.TryAdd(thing, canMergeWithExistingStacks))
{
resultingTransferredItem = thing;
item.MapHeld?.resourceCounter?.CheckUpdateResource(thing);
return thing.stackCount;
}
resultingTransferredItem = null;
if (!otherContainer.Contains(thing) && thing.stackCount > 0 && !thing.Destroyed)
{
int result = num - thing.stackCount;
if (item != thing)
{
item.TryAbsorbStack(thing, respectStackLimit: false);
}
else
{
TryAdd(thing, canMergeWithExistingStacks: false);
}
Map mapHeld = item.MapHeld;
if (mapHeld != null)
{
ResourceCounter resourceCounter = mapHeld.resourceCounter;
if (resourceCounter != null)
{
resourceCounter.CheckUpdateResource(thing);
return result;
}
return result;
}
return result;
}
return thing.stackCount;
}
public void TryTransferAllToContainer(ThingOwner other, bool canMergeWithExistingStacks = true)
{
for (int num = Count - 1; num >= 0; num--)
{
TryTransferToContainer(GetAt(num), other, canMergeWithExistingStacks);
}
}
public Thing Take(Thing thing, int count)
{
if (!Contains(thing))
{
Log.Error("Tried to take " + thing.ToStringSafe() + " but it's not here.");
return null;
}
if (count > thing.stackCount)
{
Log.Error("Tried to get " + count + " of " + thing.ToStringSafe() + " while only having " + thing.stackCount);
count = thing.stackCount;
}
if (count == thing.stackCount)
{
Remove(thing);
return thing;
}
Thing thing2 = thing.SplitOff(count);
thing2.holdingOwner = null;
return thing2;
}
public Thing Take(Thing thing)
{
return Take(thing, thing.stackCount);
}
public bool TryDrop(Thing thing, ThingPlaceMode mode, int count, out Thing lastResultingThing, Action<Thing, int> placedAction = null, Predicate<IntVec3> nearPlaceValidator = null)
{
Map rootMap = ThingOwnerUtility.GetRootMap(owner);
IntVec3 rootPosition = ThingOwnerUtility.GetRootPosition(owner);
if (rootMap == null || !rootPosition.IsValid)
{
Log.Error("Cannot drop " + thing?.ToString() + " without a dropLoc and with an owner whose map is null.");
lastResultingThing = null;
return false;
}
return TryDrop(thing, rootPosition, rootMap, mode, count, out lastResultingThing, placedAction, nearPlaceValidator);
}
public bool TryDrop(Thing thing, IntVec3 dropLoc, Map map, ThingPlaceMode mode, int count, out Thing resultingThing, Action<Thing, int> placedAction = null, Predicate<IntVec3> nearPlaceValidator = null)
{
if (!Contains(thing))
{
Log.Error("Tried to drop " + thing.ToStringSafe() + " but it's not here.");
resultingThing = null;
return false;
}
if (thing.stackCount < count)
{
Log.Error("Tried to drop " + count + " of " + thing?.ToString() + " while only having " + thing.stackCount);
count = thing.stackCount;
}
if (count == thing.stackCount)
{
if (GenDrop.TryDropSpawn(thing, dropLoc, map, mode, out resultingThing, placedAction, nearPlaceValidator))
{
Remove(thing);
return true;
}
return false;
}
Thing thing2 = thing.SplitOff(count);
if (GenDrop.TryDropSpawn(thing2, dropLoc, map, mode, out resultingThing, placedAction, nearPlaceValidator))
{
return true;
}
thing.TryAbsorbStack(thing2, respectStackLimit: false);
return false;
}
public bool TryDrop(Thing thing, ThingPlaceMode mode, out Thing lastResultingThing, Action<Thing, int> placedAction = null, Predicate<IntVec3> nearPlaceValidator = null)
{
Map rootMap = ThingOwnerUtility.GetRootMap(owner);
IntVec3 rootPosition = ThingOwnerUtility.GetRootPosition(owner);
if (rootMap == null || !rootPosition.IsValid)
{
Log.Error("Cannot drop " + thing?.ToString() + " without a dropLoc and with an owner whose map is null.");
lastResultingThing = null;
return false;
}
return TryDrop(thing, rootPosition, rootMap, mode, out lastResultingThing, placedAction, nearPlaceValidator);
}
public bool TryDrop(Thing thing, IntVec3 dropLoc, Map map, ThingPlaceMode mode, out Thing lastResultingThing, Action<Thing, int> placedAction = null, Predicate<IntVec3> nearPlaceValidator = null, bool playDropSound = true)
{
if (!Contains(thing))
{
Log.Error(owner.ToStringSafe() + " container tried to drop " + thing.ToStringSafe() + " which it didn't contain.");
lastResultingThing = null;
return false;
}
if (GenDrop.TryDropSpawn(thing, dropLoc, map, mode, out lastResultingThing, placedAction, nearPlaceValidator, playDropSound))
{
Remove(thing);
return true;
}
return false;
}
public bool TryDropAll(IntVec3 dropLoc, Map map, ThingPlaceMode mode, Action<Thing, int> placeAction = null, Predicate<IntVec3> nearPlaceValidator = null, bool playDropSound = true)
{
bool result = true;
for (int num = Count - 1; num >= 0; num--)
{
if (!TryDrop(GetAt(num), dropLoc, map, mode, out var _, placeAction, nearPlaceValidator, playDropSound))
{
result = false;
}
}
return result;
}
public bool Contains(ThingDef def)
{
return Contains(def, 1);
}
public bool Contains(ThingDef def, int minCount)
{
if (minCount <= 0)
{
return true;
}
int num = 0;
int count = Count;
for (int i = 0; i < count; i++)
{
if (GetAt(i).def == def)
{
num += GetAt(i).stackCount;
}
if (num >= minCount)
{
return true;
}
}
return false;
}
public int TotalStackCountOfDef(ThingDef def)
{
int num = 0;
int count = Count;
for (int i = 0; i < count; i++)
{
if (GetAt(i).def == def)
{
num += GetAt(i).stackCount;
}
}
return num;
}
public void Notify_ContainedItemDestroyed(Thing t)
{
if (ThingOwnerUtility.ShouldAutoRemoveDestroyedThings(owner))
{
Remove(t);
}
}
protected virtual void NotifyAdded(Thing item)
{
if (ThingOwnerUtility.ShouldAutoExtinguishInnerThings(owner) && item.HasAttachment(ThingDefOf.Fire))
{
item.GetAttachment(ThingDefOf.Fire).Destroy();
}
if (ThingOwnerUtility.ShouldRemoveDesignationsOnAddedThings(owner))
{
List<Map> maps = Find.Maps;
for (int i = 0; i < maps.Count; i++)
{
maps[i].designationManager.RemoveAllDesignationsOn(item);
}
}
if ((owner is Thing thing && thing.Faction.IsPlayerSafe()) || (owner is WorldObject worldObject && worldObject.Faction.IsPlayerSafe()) || (owner is Pawn_InventoryTracker pawn_InventoryTracker && pawn_InventoryTracker.pawn.Faction.IsPlayerSafe()))
{
item.EverSeenByPlayer = true;
}
if (owner is CompTransporter compTransporter)
{
compTransporter.Notify_ThingAdded(item);
}
if (owner is Caravan caravan)
{
caravan.Notify_PawnAdded((Pawn)item);
}
if (owner is Pawn_ApparelTracker pawn_ApparelTracker)
{
pawn_ApparelTracker.Notify_ApparelAdded((Apparel)item);
if (pawn_ApparelTracker.pawn.Faction.IsPlayerSafe())
{
item.EverSeenByPlayer = true;
}
}
if (owner is Pawn_EquipmentTracker pawn_EquipmentTracker)
{
pawn_EquipmentTracker.Notify_EquipmentAdded((ThingWithComps)item);
if (pawn_EquipmentTracker.pawn.Faction.IsPlayerSafe())
{
item.EverSeenByPlayer = true;
}
}
NotifyColonistBarIfColonistCorpse(item);
this.OnContentsChanged?.Invoke();
}
protected void NotifyAddedAndMergedWith(Thing item, int mergedCount)
{
if (owner is CompTransporter compTransporter)
{
compTransporter.Notify_ThingAddedAndMergedWith(item, mergedCount);
}
}
protected virtual void NotifyRemoved(Thing item)
{
if (owner is Pawn_InventoryTracker pawn_InventoryTracker)
{
pawn_InventoryTracker.Notify_ItemRemoved(item);
}
if (owner is Pawn_ApparelTracker pawn_ApparelTracker)
{
pawn_ApparelTracker.Notify_ApparelRemoved((Apparel)item);
}
if (owner is Pawn_EquipmentTracker pawn_EquipmentTracker)
{
pawn_EquipmentTracker.Notify_EquipmentRemoved((ThingWithComps)item);
}
if (owner is Caravan caravan)
{
caravan.Notify_PawnRemoved((Pawn)item);
}
NotifyColonistBarIfColonistCorpse(item);
this.OnContentsChanged?.Invoke();
}
private void NotifyColonistBarIfColonistCorpse(Thing thing)
{
if (thing is Corpse { Bugged: false } corpse && corpse.InnerPawn.Faction != null && corpse.InnerPawn.Faction.IsPlayer && Current.ProgramState == ProgramState.Playing)
{
Find.ColonistBar.MarkColonistsDirty();
}
}
void IList<Thing>.Insert(int index, Thing item)
{
throw new InvalidOperationException("ThingOwner doesn't allow inserting individual elements at any position.");
}
void ICollection<Thing>.Add(Thing item)
{
TryAdd(item);
}
void ICollection<Thing>.CopyTo(Thing[] array, int arrayIndex)
{
for (int i = 0; i < Count; i++)
{
array[i + arrayIndex] = GetAt(i);
}
}
IEnumerator<Thing> IEnumerable<Thing>.GetEnumerator()
{
for (int i = 0; i < Count; i++)
{
yield return GetAt(i);
}
}
IEnumerator IEnumerable.GetEnumerator()
{
for (int i = 0; i < Count; i++)
{
yield return GetAt(i);
}
}
}
```
---
**文件路径:** `C:\Steam\steamapps\common\RimWorld\Data\dll1.6\Verse.AI\Toils_Haul.txt`
**相似度:** 0.6124
```csharp
public class Toils_Haul
{
public static bool ErrorCheckForCarry(Pawn pawn, Thing haulThing, bool canTakeFromInventory = false)
{
if (!haulThing.SpawnedOrAnyParentSpawned || (!canTakeFromInventory && !haulThing.Spawned))
{
Log.Message(pawn?.ToString() + " tried to start carry " + haulThing?.ToString() + " which isn't spawned.");
pawn.jobs.EndCurrentJob(JobCondition.Incompletable);
return true;
}
if (haulThing.stackCount == 0)
{
Log.Message(pawn?.ToString() + " tried to start carry " + haulThing?.ToString() + " which had stackcount 0.");
pawn.jobs.EndCurrentJob(JobCondition.Incompletable);
return true;
}
if (pawn.jobs.curJob.count <= 0)
{
Log.Error("Invalid count: " + pawn.jobs.curJob.count + ", setting to 1. Job was " + pawn.jobs.curJob);
pawn.jobs.curJob.count = 1;
}
return false;
}
public static Toil StartCarryThing(TargetIndex haulableInd, bool putRemainderInQueue = false, bool subtractNumTakenFromJobCount = false, bool failIfStackCountLessThanJobCount = false, bool reserve = true, bool canTakeFromInventory = false)
{
Toil toil = ToilMaker.MakeToil("StartCarryThing");
toil.initAction = delegate
{
Pawn actor = toil.actor;
Job curJob = actor.jobs.curJob;
Thing thing = curJob.GetTarget(haulableInd).Thing;
if (!ErrorCheckForCarry(actor, thing, canTakeFromInventory))
{
if (curJob.count == 0)
{
throw new Exception($"StartCarryThing job had count = {curJob.count}. Job: {curJob}");
}
int num = actor.carryTracker.AvailableStackSpace(thing.def);
if (num <= 0)
{
int num2 = actor.carryTracker.MaxStackSpaceEver(thing.def);
int num3 = 0;
if (actor.carryTracker.CarriedThing != null)
{
num3 = actor.carryTracker.CarriedThing.stackCount;
}
throw new Exception($"StartCarryThing got availableStackSpace {num} (haulTarg {thing}, Job: {curJob}, maximum: {num2}, carrying: {num3})");
}
if (failIfStackCountLessThanJobCount && thing.stackCount < curJob.count)
{
actor.jobs.curDriver.EndJobWith(JobCondition.Incompletable);
}
else
{
int num4 = Mathf.Min(curJob.count, num, thing.stackCount);
if (num4 <= 0)
{
int num5 = actor.carryTracker.MaxStackSpaceEver(thing.def);
int num6 = 0;
if (actor.carryTracker.CarriedThing != null)
{
num6 = actor.carryTracker.CarriedThing.stackCount;
}
throw new Exception($"StartCarryThing zero or negative desiredNumToTake ({num4}), curJob.count: {curJob.count}, availableStackSpace: {num} (maximum: {num5}, carrying: {num6}), haulTarg.stackCount: {thing.stackCount}");
}
int stackCount = thing.stackCount;
int num7 = actor.carryTracker.TryStartCarry(thing, num4, reserve);
if (num7 == 0)
{
actor.jobs.EndCurrentJob(JobCondition.Incompletable);
}
if (num7 < stackCount)
{
int num8 = curJob.count - num7;
if (putRemainderInQueue && num8 > 0)
{
curJob.GetTargetQueue(haulableInd).Insert(0, thing);
Job job = curJob;
if (job.countQueue == null)
{
job.countQueue = new List<int>();
}
curJob.countQueue.Insert(0, num8);
}
else if (actor.Map.reservationManager.ReservedBy(thing, actor, curJob))
{
actor.Map.reservationManager.Release(thing, actor, curJob);
}
}
if (subtractNumTakenFromJobCount)
{
curJob.count -= num7;
}
curJob.SetTarget(haulableInd, actor.carryTracker.CarriedThing);
actor.records.Increment(RecordDefOf.ThingsHauled);
}
}
};
return toil;
}
public static Toil StoreThingJob(TargetIndex thingIndex)
{
Toil toil = ToilMaker.MakeToil("StoreThingJob");
toil.initAction = delegate
{
Pawn actor = toil.actor;
Job curJob = actor.CurJob;
Thing thing = curJob.GetTarget(thingIndex).Thing;
Job job = HaulAIUtility.HaulToStorageJob(actor, thing, curJob.playerForced);
if (job != null)
{
actor.jobs.TryTakeOrderedJob(job, JobTag.Misc);
}
};
return toil;
}
public static Toil DropCarriedThing()
{
Toil toil = ToilMaker.MakeToil("DropCarriedThing");
toil.initAction = delegate
{
Pawn actor = toil.actor;
Thing resultingThing;
if (actor.carryTracker.CarriedThing == null)
{
Log.Error(actor?.ToString() + " tried to drop carried thing but is not carrying anything.");
}
else if (!actor.carryTracker.TryDropCarriedThing(actor.Position, ThingPlaceMode.Direct, out resultingThing))
{
actor.jobs.EndCurrentJob(JobCondition.Incompletable);
}
};
return toil;
}
public static Toil JumpIfAlsoCollectingNextTargetInQueue(Toil gotoGetTargetToil, TargetIndex ind)
{
Toil toil = ToilMaker.MakeToil("JumpIfAlsoCollectingNextTargetInQueue");
toil.initAction = delegate
{
Pawn actor = toil.actor;
Job curJob = actor.jobs.curJob;
List<LocalTargetInfo> targetQueue = curJob.GetTargetQueue(ind);
if (!targetQueue.NullOrEmpty() && curJob.count > 0)
{
if (actor.carryTracker.CarriedThing == null)
{
Log.Error("JumpToAlsoCollectTargetInQueue run on " + actor?.ToString() + " who is not carrying something.");
}
else if (actor.carryTracker.AvailableStackSpace(actor.carryTracker.CarriedThing.def) > 0)
{
for (int i = 0; i < targetQueue.Count; i++)
{
if (!GenAI.CanUseItemForWork(actor, targetQueue[i].Thing))
{
actor.jobs.EndCurrentJob(JobCondition.Incompletable);
break;
}
if (targetQueue[i].Thing.def == actor.carryTracker.CarriedThing.def)
{
curJob.SetTarget(ind, targetQueue[i].Thing);
targetQueue.RemoveAt(i);
actor.jobs.curDriver.JumpToToil(gotoGetTargetToil);
break;
}
}
}
}
};
return toil;
}
public static Toil CheckForGetOpportunityDuplicate(Toil getHaulTargetToil, TargetIndex haulableInd, TargetIndex storeCellInd, bool takeFromValidStorage = false, Predicate<Thing> extraValidator = null)
{
Toil toil = ToilMaker.MakeToil("CheckForGetOpportunityDuplicate");
toil.initAction = delegate
{
Pawn actor = toil.actor;
Job curJob = actor.jobs.curJob;
if (actor.carryTracker.CarriedThing.def.stackLimit != 1 && !actor.carryTracker.Full && curJob.count > 0)
{
Thing thing = GenClosest.ClosestThingReachable(actor.Position, actor.Map, ThingRequest.ForGroup(ThingRequestGroup.HaulableAlways), PathEndMode.ClosestTouch, TraverseParms.For(actor), 8f, DupeValidator);
if (thing != null)
{
curJob.SetTarget(haulableInd, thing);
actor.jobs.curDriver.JumpToToil(getHaulTargetToil);
}
}
bool DupeValidator(Thing t)
{
if (!t.Spawned)
{
return false;
}
if (t.def != actor.carryTracker.CarriedThing.def)
{
return false;
}
if (!t.CanStackWith(actor.carryTracker.CarriedThing))
{
return false;
}
if (t.IsForbidden(actor))
{
return false;
}
if (!t.IsSociallyProper(actor, forPrisoner: false, animalsCare: true))
{
return false;
}
if (takeFromValidStorage && storeCellInd != 0 && curJob.GetTarget(storeCellInd).Cell.TryGetSlotGroup(actor.Map, out var group) && t.TryGetValidStoragePriority(out var priority) && (int)priority >= (int)group.Settings.Priority)
{
return false;
}
if (storeCellInd != 0 && !curJob.GetTarget(storeCellInd).Cell.IsValidStorageFor(actor.Map, t))
{
return false;
}
if (!actor.CanReserve(t))
{
return false;
}
if (extraValidator != null && !extraValidator(t))
{
return false;
}
return true;
}
};
return toil;
}
public static Toil CarryHauledThingToCell(TargetIndex squareIndex, PathEndMode pathEndMode = PathEndMode.ClosestTouch)
{
Toil toil = ToilMaker.MakeToil("CarryHauledThingToCell");
toil.initAction = delegate
{
IntVec3 cell3 = toil.actor.jobs.curJob.GetTarget(squareIndex).Cell;
toil.actor.pather.StartPath(cell3, pathEndMode);
};
toil.defaultCompleteMode = ToilCompleteMode.PatherArrival;
toil.AddEndCondition(delegate
{
Pawn actor2 = toil.actor;
IntVec3 cell2 = actor2.jobs.curJob.GetTarget(squareIndex).Cell;
CompPushable compPushable2 = actor2.carryTracker.CarriedThing.TryGetComp<CompPushable>();
if (compPushable2 != null)
{
Vector3 v = actor2.Position.ToVector3() + compPushable2.drawPos;
if (new IntVec3(v) == cell2)
{
return JobCondition.Succeeded;
}
}
return JobCondition.Ongoing;
});
toil.AddFailCondition(delegate
{
Pawn actor = toil.actor;
IntVec3 cell = actor.jobs.curJob.GetTarget(squareIndex).Cell;
if (actor.carryTracker.CarriedThing == null)
{
return true;
}
if (actor.jobs.curJob.haulMode == HaulMode.ToCellStorage && !cell.IsValidStorageFor(actor.Map, actor.carryTracker.CarriedThing))
{
return true;
}
CompPushable compPushable = actor.carryTracker.CarriedThing.TryGetComp<CompPushable>();
return (compPushable != null && !compPushable.canBePushed) ? true : false;
});
return toil;
}
public static Toil PlaceCarriedThingInCellFacing(TargetIndex facingTargetInd)
{
Toil toil = ToilMaker.MakeToil("PlaceCarriedThingInCellFacing");
toil.initAction = delegate
{
Pawn actor = toil.actor;
if (actor.carryTracker.CarriedThing == null)
{
Log.Error(actor?.ToString() + " tried to place hauled thing in facing cell but is not hauling anything.");
}
else
{
LocalTargetInfo target = actor.CurJob.GetTarget(facingTargetInd);
IntVec3 intVec = ((!target.HasThing) ? target.Cell : target.Thing.OccupiedRect().ClosestCellTo(actor.Position));
IntVec3 dropLoc = actor.Position + Pawn_RotationTracker.RotFromAngleBiased((actor.Position - intVec).AngleFlat).FacingCell;
if (!actor.carryTracker.TryDropCarriedThing(dropLoc, ThingPlaceMode.Direct, out var _))
{
actor.jobs.EndCurrentJob(JobCondition.Incompletable);
}
}
};
return toil;
}
public static Toil PlaceHauledThingInCell(TargetIndex cellInd, Toil nextToilOnPlaceFailOrIncomplete, bool storageMode, bool tryStoreInSameStorageIfSpotCantHoldWholeStack = false)
{
Toil toil = ToilMaker.MakeToil("PlaceHauledThingInCell");
toil.initAction = delegate
{
Pawn actor = toil.actor;
Job curJob = actor.jobs.curJob;
IntVec3 cell = curJob.GetTarget(cellInd).Cell;
if (actor.carryTracker.CarriedThing == null)
{
Log.Error(actor?.ToString() + " tried to place hauled thing in cell but is not hauling anything.");
}
else
{
SlotGroup slotGroup = actor.Map.haulDestinationManager.SlotGroupAt(cell);
if (slotGroup != null && slotGroup.Settings.AllowedToAccept(actor.carryTracker.CarriedThing))
{
actor.Map.designationManager.TryRemoveDesignationOn(actor.carryTracker.CarriedThing, DesignationDefOf.Haul);
}
Action<Thing, int> placedAction = null;
if (curJob.def == JobDefOf.DoBill || curJob.def == JobDefOf.RecolorApparel || curJob.def == JobDefOf.RefuelAtomic || curJob.def == JobDefOf.RearmTurretAtomic)
{
placedAction = delegate(Thing th, int added)
{
HaulAIUtility.UpdateJobWithPlacedThings(curJob, th, added);
};
}
if (!actor.carryTracker.TryDropCarriedThing(cell, ThingPlaceMode.Direct, out var _, placedAction))
{
if (storageMode)
{
IntVec3 storeCell;
if (nextToilOnPlaceFailOrIncomplete != null && ((tryStoreInSameStorageIfSpotCantHoldWholeStack && StoreUtility.TryFindBestBetterStoreCellForIn(actor.carryTracker.CarriedThing, actor, actor.Map, StoragePriority.Unstored, actor.Faction, curJob.bill.GetSlotGroup(), out var foundCell)) || StoreUtility.TryFindBestBetterStoreCellFor(actor.carryTracker.CarriedThing, actor, actor.Map, StoragePriority.Unstored, actor.Faction, out foundCell)))
{
if (actor.CanReserve(foundCell))
{
actor.Reserve(foundCell, actor.CurJob);
}
actor.CurJob.SetTarget(cellInd, foundCell);
actor.jobs.curDriver.JumpToToil(nextToilOnPlaceFailOrIncomplete);
}
else if (HaulAIUtility.CanHaulAside(actor, actor.carryTracker.CarriedThing, out storeCell))
{
curJob.SetTarget(cellInd, storeCell);
curJob.count = int.MaxValue;
curJob.haulOpportunisticDuplicates = false;
curJob.haulMode = HaulMode.ToCellNonStorage;
if (nextToilOnPlaceFailOrIncomplete != null)
{
actor.jobs.curDriver.JumpToToil(nextToilOnPlaceFailOrIncomplete);
}
}
else
{
Log.Warning($"Incomplete haul for {actor}: Could not find anywhere to put {actor.carryTracker.CarriedThing} near {actor.Position}. Destroying. This should be very uncommon!");
actor.carryTracker.CarriedThing.Destroy();
}
}
else if (nextToilOnPlaceFailOrIncomplete != null)
{
actor.jobs.curDriver.JumpToToil(nextToilOnPlaceFailOrIncomplete);
}
}
}
};
return toil;
}
public static Toil CarryHauledThingToContainer()
{
Toil gotoDest = ToilMaker.MakeToil("CarryHauledThingToContainer");
gotoDest.initAction = delegate
{
gotoDest.actor.pather.StartPath(gotoDest.actor.jobs.curJob.targetB.Thing, PathEndMode.Touch);
};
gotoDest.AddFailCondition(delegate
{
Thing thing = gotoDest.actor.jobs.curJob.targetB.Thing;
if (thing.Destroyed || (!gotoDest.actor.jobs.curJob.ignoreForbidden && thing.IsForbidden(gotoDest.actor)))
{
return true;
}
ThingOwner thingOwner = thing.TryGetInnerInteractableThingOwner();
return (thingOwner != null && !thingOwner.CanAcceptAnyOf(gotoDest.actor.carryTracker.CarriedThing)) ? true : false;
});
gotoDest.defaultCompleteMode = ToilCompleteMode.PatherArrival;
return gotoDest;
}
public static Toil DepositHauledThingInContainer(TargetIndex containerInd, TargetIndex reserveForContainerInd, Action onDeposited = null)
{
Toil toil = ToilMaker.MakeToil("DepositHauledThingInContainer");
toil.initAction = delegate
{
Pawn actor = toil.actor;
Job curJob = actor.jobs.curJob;
if (actor.carryTracker.CarriedThing == null)
{
Log.Error(actor?.ToString() + " tried to place hauled thing in container but is not hauling anything.");
}
else
{
Thing thing = curJob.GetTarget(containerInd).Thing;
ThingOwner thingOwner = thing.TryGetInnerInteractableThingOwner();
if (thingOwner != null)
{
int num = actor.carryTracker.CarriedThing.stackCount;
if (thing is IHaulEnroute haulEnroute)
{
ThingDef def = actor.carryTracker.CarriedThing.def;
num = Mathf.Min(haulEnroute.GetSpaceRemainingWithEnroute(def, actor), num);
if (reserveForContainerInd != 0)
{
Thing thing2 = curJob.GetTarget(reserveForContainerInd).Thing;
if (!thing2.DestroyedOrNull() && thing2 != haulEnroute && thing2 is IHaulEnroute enroute)
{
int spaceRemainingWithEnroute = enroute.GetSpaceRemainingWithEnroute(def, actor);
num = Mathf.Min(num, actor.carryTracker.CarriedThing.stackCount - spaceRemainingWithEnroute);
}
}
}
Thing carriedThing = actor.carryTracker.CarriedThing;
int num2 = actor.carryTracker.innerContainer.TryTransferToContainer(carriedThing, thingOwner, num);
if (num2 != 0)
{
if (thing is IHaulEnroute container)
{
thing.Map.enrouteManager.ReleaseFor(container, actor);
}
if (thing is INotifyHauledTo notifyHauledTo)
{
notifyHauledTo.Notify_HauledTo(actor, carriedThing, num2);
}
if (thing is ThingWithComps thingWithComps)
{
foreach (ThingComp allComp in thingWithComps.AllComps)
{
if (allComp is INotifyHauledTo notifyHauledTo2)
{
notifyHauledTo2.Notify_HauledTo(actor, carriedThing, num2);
}
}
}
if (curJob.def == JobDefOf.DoBill)
{
HaulAIUtility.UpdateJobWithPlacedThings(curJob, carriedThing, num2);
}
onDeposited?.Invoke();
}
}
else if (curJob.GetTarget(containerInd).Thing.def.Minifiable)
{
actor.carryTracker.innerContainer.ClearAndDestroyContents();
}
else
{
Log.Error("Could not deposit hauled thing in container: " + curJob.GetTarget(containerInd).Thing);
}
}
};
return toil;
}
public static Toil JumpToCarryToNextContainerIfPossible(Toil carryToContainerToil, TargetIndex primaryTargetInd)
{
Toil toil = ToilMaker.MakeToil("JumpToCarryToNextContainerIfPossible");
toil.debugName = "Jump carry if possible";
toil.initAction = delegate
{
Pawn actor = toil.actor;
Job curJob = actor.jobs.curJob;
if (actor.carryTracker.CarriedThing != null && curJob.targetQueueB != null && curJob.targetQueueB.Count > 0)
{
if (TryGetNextDestinationFromQueue(primaryTargetInd, TargetIndex.B, actor.carryTracker.CarriedThing.def, curJob, actor, out var nextTarget))
{
curJob.targetQueueB.RemoveAll((LocalTargetInfo target) => target.Thing == nextTarget);
curJob.targetB = nextTarget;
curJob.targetC = nextTarget;
actor.jobs.curDriver.JumpToToil(carryToContainerToil);
}
}
};
return toil;
}
public static bool TryGetNextDestinationFromQueue(TargetIndex primaryIndex, TargetIndex destIndex, ThingDef stuff, Job job, Pawn actor, out Thing target)
{
Thing primaryTarget = job.GetTarget(primaryIndex).Thing;
target = null;
if (actor.carryTracker?.CarriedThing == null)
{
return false;
}
bool hasSpareItems = actor.carryTracker.CarriedThing.stackCount > 0;
if (primaryTarget != null && primaryTarget.Spawned && primaryTarget is IHaulEnroute enroute)
{
int spaceRemainingWithEnroute = enroute.GetSpaceRemainingWithEnroute(stuff, actor);
hasSpareItems = actor.carryTracker.CarriedThing.stackCount > spaceRemainingWithEnroute;
}
target = GenClosest.ClosestThing_Global_Reachable(actor.Position, actor.Map, from x in job.GetTargetQueue(destIndex)
select x.Thing, PathEndMode.Touch, TraverseParms.For(actor), 99999f, Validator);
return target != null;
bool Validator(Thing th)
{
if (!(th is IHaulEnroute enroute2))
{
return false;
}
if (enroute2.GetSpaceRemainingWithEnroute(stuff, actor) <= 0)
{
return false;
}
if (th != primaryTarget && !hasSpareItems)
{
return false;
}
return true;
}
}
public static Toil TakeToInventory(TargetIndex ind, int count)
{
return TakeToInventory(ind, count, null, null);
}
private static Toil TakeToInventory(TargetIndex ind, int? count, Func<int> countGetter, Func<Thing, int> countGetterPassingThing)
{
Toil takeThing = ToilMaker.MakeToil("TakeToInventory");
takeThing.initAction = delegate
{
Pawn actor = takeThing.actor;
Thing thing = actor.CurJob.GetTarget(ind).Thing;
if (!ErrorCheckForCarry(actor, thing))
{
int num = Mathf.Min(count ?? countGetterPassingThing?.Invoke(thing) ?? countGetter(), thing.stackCount);
if (actor.CurJob.checkEncumbrance)
{
num = Math.Min(num, MassUtility.CountToPickUpUntilOverEncumbered(actor, thing));
}
if (num <= 0)
{
actor.jobs.curDriver.ReadyForNextToil();
}
else
{
actor.inventory.GetDirectlyHeldThings().TryAdd(thing.SplitOff(num));
if (thing.def.ingestible != null && (int)thing.def.ingestible.preferability <= 5)
{
actor.mindState.lastInventoryRawFoodUseTick = Find.TickManager.TicksGame;
}
thing.def.soundPickup.PlayOneShot(new TargetInfo(actor.Position, actor.Map));
}
}
};
return takeThing;
}
public static Toil TakeToInventory(TargetIndex ind, Func<int> countGetter)
{
return TakeToInventory(ind, null, countGetter, null);
}
public static Toil TakeToInventory(TargetIndex ind, Func<Thing, int> countGetter)
{
return TakeToInventory(ind, null, null, countGetter);
}
public static Toil TakeFromOtherInventory(Thing item, ThingOwner taker, ThingOwner holder, int count = -1, TargetIndex indexToSet = TargetIndex.None)
{
Toil toil = ToilMaker.MakeToil("TakeFromOtherInventory");
toil.initAction = delegate
{
if (!holder.Contains(item))
{
toil.actor.jobs.EndCurrentJob(JobCondition.Incompletable);
}
else
{
count = ((count < 0) ? toil.actor.jobs.curJob.count : count);
holder.TryTransferToContainer(item, taker, Mathf.Min(item.stackCount, count), out var resultingTransferredItem);
if (resultingTransferredItem == null)
{
Log.Warning($"Taker {toil.actor.Label} unable to take count {count} of thing {item.Label} from holder's inventory");
toil.actor.jobs.EndCurrentJob(JobCondition.Incompletable);
}
else if (indexToSet != 0)
{
toil.actor.jobs.curJob.SetTarget(indexToSet, resultingTransferredItem);
}
}
};
return toil;
}
public static Toil CheckItemCarriedByOtherPawn(Thing item, TargetIndex targetPawnIfCarried = TargetIndex.None, Toil jumpIfCarriedByOther = null)
{
Toil toil = ToilMaker.MakeToil("CheckItemCarriedByOtherPawn");
toil.initAction = delegate
{
Pawn pawn = (item?.ParentHolder as Pawn_InventoryTracker)?.pawn;
if (pawn != null && pawn != toil.actor)
{
if (targetPawnIfCarried != 0)
{
toil.actor.jobs.curJob.SetTarget(targetPawnIfCarried, pawn);
}
if (jumpIfCarriedByOther != null)
{
toil.actor.jobs.curDriver.JumpToToil(jumpIfCarriedByOther);
}
}
};
toil.defaultCompleteMode = ToilCompleteMode.Instant;
toil.atomicWithPrevious = true;
return toil;
}
}
```
---
**文件路径:** `C:\Steam\steamapps\common\RimWorld\Data\dll1.6\RimWorld\PawnUtility.txt`
**相似度:** 0.5783
```csharp
public static class PawnUtility
{
private static List<Pawn> tmpPawns = new List<Pawn>();
private static List<string> tmpPawnKindsStr = new List<string>();
private static HashSet<PawnKindDef> tmpAddedPawnKinds = new HashSet<PawnKindDef>();
private static List<PawnKindDef> tmpPawnKinds = new List<PawnKindDef>();
private static List<Thing> tmpThings = new List<Thing>();
public static Faction GetFactionLeaderFaction(Pawn pawn)
{
List<Faction> allFactionsListForReading = Find.FactionManager.AllFactionsListForReading;
for (int i = 0; i < allFactionsListForReading.Count; i++)
{
if (allFactionsListForReading[i].leader == pawn)
{
return allFactionsListForReading[i];
}
}
return null;
}
public static bool IsFactionLeader(Pawn pawn)
{
return GetFactionLeaderFaction(pawn) != null;
}
public static bool IsInteractionBlocked(this Pawn pawn, InteractionDef interaction, bool isInitiator, bool isRandom)
{
MentalStateDef mentalStateDef = pawn.MentalStateDef;
if (mentalStateDef != null)
{
if (isRandom)
{
return mentalStateDef.blockRandomInteraction;
}
if (interaction == null)
{
return false;
}
List<InteractionDef> list = (isInitiator ? mentalStateDef.blockInteractionInitiationExcept : mentalStateDef.blockInteractionRecipientExcept);
if (list != null)
{
return !list.Contains(interaction);
}
return false;
}
List<Hediff> hediffs = pawn.health.hediffSet.hediffs;
for (int i = 0; i < hediffs.Count; i++)
{
if (hediffs[i].def.blocksSocialInteraction)
{
return true;
}
}
Lord lord = pawn.GetLord();
if (lord != null && lord.BlocksSocialInteraction(pawn))
{
return true;
}
return false;
}
public static bool IsKidnappedPawn(Pawn pawn)
{
List<Faction> allFactionsListForReading = Find.FactionManager.AllFactionsListForReading;
for (int i = 0; i < allFactionsListForReading.Count; i++)
{
if (allFactionsListForReading[i].kidnapped.KidnappedPawnsListForReading.Contains(pawn))
{
return true;
}
}
return false;
}
public static bool IsTravelingInTransportPodWorldObject(Pawn pawn)
{
if (!pawn.IsWorldPawn() || !ThingOwnerUtility.AnyParentIs<ActiveTransporterInfo>(pawn))
{
return ThingOwnerUtility.AnyParentIs<TravellingTransporters>(pawn);
}
return true;
}
public static bool ForSaleBySettlement(Pawn pawn)
{
return pawn.ParentHolder is Settlement_TraderTracker;
}
public static bool IsCarrying(this Pawn pawn)
{
if (!pawn.Destroyed && pawn.carryTracker != null)
{
return pawn.carryTracker.CarriedThing != null;
}
return false;
}
public static bool IsCarryingPawn(this Pawn pawn, Pawn carryPawn = null)
{
if (pawn.carryTracker != null && pawn.carryTracker.CarriedThing is Pawn)
{
if (carryPawn != null)
{
return pawn.carryTracker.CarriedThing == carryPawn;
}
return true;
}
return false;
}
public static bool IsCarryingThing(this Pawn pawn, Thing carriedThing)
{
if (pawn.carryTracker != null && pawn.carryTracker.CarriedThing != null)
{
return pawn.carryTracker.CarriedThing == carriedThing;
}
return false;
}
public static void TryDestroyStartingColonistFamily(Pawn pawn)
{
if (!pawn.relations.RelatedPawns.Any((Pawn x) => Find.GameInitData.startingAndOptionalPawns.Contains(x)))
{
DestroyStartingColonistFamily(pawn);
}
}
public static void DestroyStartingColonistFamily(Pawn pawn)
{
foreach (Pawn item in pawn.relations.RelatedPawns.ToList())
{
if (!Find.GameInitData.startingAndOptionalPawns.Contains(item))
{
WorldPawnSituation situation = Find.WorldPawns.GetSituation(item);
if (situation == WorldPawnSituation.Free || situation == WorldPawnSituation.Dead)
{
Find.WorldPawns.RemovePawn(item);
Find.WorldPawns.PassToWorld(item, PawnDiscardDecideMode.Discard);
}
}
}
}
public static bool EnemiesAreNearby(Pawn pawn, int regionsToScan = 9, bool passDoors = false, float maxDistance = -1f, int maxCount = 1, bool invisible = false)
{
TraverseParms tp = (passDoors ? TraverseParms.For(TraverseMode.PassDoors) : TraverseParms.For(pawn));
int count = 0;
RegionTraverser.BreadthFirstTraverse(pawn.Position, pawn.Map, (Region from, Region to) => to.Allows(tp, isDestination: false), delegate(Region r)
{
List<Thing> list = r.ListerThings.ThingsInGroup(ThingRequestGroup.AttackTarget);
for (int i = 0; i < list.Count; i++)
{
Thing thing = list[i];
if ((maxDistance <= 0f || thing.Position.InHorDistOf(pawn.Position, maxDistance)) && thing.HostileTo(pawn) && (invisible || !(thing is Pawn pawn2) || !pawn2.IsPsychologicallyInvisible()))
{
count++;
}
}
return count >= maxCount;
}, regionsToScan);
return count >= maxCount;
}
public static bool WillSoonHaveBasicNeed(Pawn p, float thresholdOffset = 0.05f)
{
if (p.needs == null)
{
return false;
}
if (p.needs.rest != null && p.needs.rest.CurLevel < 0.28f + thresholdOffset)
{
return true;
}
if (p.needs.food != null && p.needs.food.CurLevelPercentage < p.needs.food.PercentageThreshHungry + thresholdOffset)
{
return true;
}
return false;
}
public static bool CanCasuallyInteractNow(this Pawn p, bool twoWayInteraction = false, bool canInteractWhileSleeping = false, bool canInteractWhileRoaming = false, bool canInteractWhileDrafted = false)
{
if (p.Drafted && !canInteractWhileDrafted)
{
return false;
}
if (p.IsPsychologicallyInvisible())
{
return false;
}
if (ThinkNode_ConditionalShouldFollowMaster.ShouldFollowMaster(p))
{
return false;
}
if (p.InAggroMentalState)
{
return false;
}
if (p.InMentalState && p.MentalStateDef == MentalStateDefOf.Roaming && !canInteractWhileRoaming)
{
return false;
}
if (!p.Awake() && !canInteractWhileSleeping)
{
return false;
}
if (p.IsFormingCaravan())
{
return false;
}
Job curJob = p.CurJob;
if (curJob != null && twoWayInteraction && (!curJob.def.casualInterruptible || !curJob.playerForced))
{
return false;
}
return true;
}
public static IEnumerable<Pawn> SpawnedMasteredPawns(Pawn master)
{
if (Current.ProgramState != ProgramState.Playing || master.Faction == null || !master.RaceProps.Humanlike || !master.Spawned)
{
yield break;
}
List<Pawn> pawns = master.Map.mapPawns.SpawnedPawnsInFaction(master.Faction);
for (int i = 0; i < pawns.Count; i++)
{
if (pawns[i].playerSettings != null && pawns[i].playerSettings.Master == master)
{
yield return pawns[i];
}
}
}
public static bool InValidState(Pawn p)
{
if (p.health == null)
{
return false;
}
if (!p.Dead && (p.stances == null || p.mindState == null || p.needs == null || p.ageTracker == null))
{
return false;
}
return true;
}
public static PawnPosture GetPosture(this Pawn p)
{
PawnPosture pawnPosture = (p.Dead ? PawnPosture.LayingOnGroundNormal : ((!ModsConfig.BiotechActive || !p.IsCharging()) ? ((!(p.ParentHolder is IThingHolderWithDrawnPawn thingHolderWithDrawnPawn)) ? (p.Downed ? ((p.jobs == null || !p.jobs.posture.Laying()) ? PawnPosture.LayingOnGroundNormal : p.jobs.posture) : ((p.jobs != null) ? p.jobs.posture : PawnPosture.Standing)) : thingHolderWithDrawnPawn.HeldPawnPosture) : PawnPosture.Standing));
Pawn_MindState mindState = p.mindState;
if (mindState != null && mindState.duty?.def?.forceFaceUpPosture == true && pawnPosture != 0)
{
pawnPosture |= PawnPosture.FaceUpMask;
}
return pawnPosture;
}
public static void ForceWait(Pawn pawn, int ticks, Thing faceTarget = null, bool maintainPosture = false, bool maintainSleep = false)
{
if (ticks <= 0)
{
Log.ErrorOnce("Forcing a wait for zero ticks", 47045639);
}
JobDef def = (maintainPosture ? JobDefOf.Wait_MaintainPosture : JobDefOf.Wait);
if (pawn.IsDeactivated())
{
def = JobDefOf.Deactivated;
}
if (pawn.IsSelfShutdown())
{
def = JobDefOf.SelfShutdown;
}
else if (pawn.InBed())
{
def = (pawn.Awake() ? JobDefOf.LayDownAwake : JobDefOf.LayDown);
}
else if (!pawn.health.capacities.CanBeAwake)
{
def = JobDefOf.Wait_Downed;
}
else if (maintainSleep && !pawn.Awake())
{
def = JobDefOf.Wait_Asleep;
}
Job job = JobMaker.MakeJob(def, faceTarget);
if (maintainSleep && !pawn.Awake())
{
job.forceSleep = true;
job.targetA = pawn.Position;
}
if (pawn.InBed())
{
job.targetA = pawn.CurrentBed();
}
job.expiryInterval = ticks;
pawn.jobs.StartJob(job, JobCondition.InterruptForced, null, resumeCurJobAfterwards: true);
}
public static void GainComfortFromCellIfPossible(this Pawn p, int delta, bool chairsOnly = false)
{
if (p.Spawned && p.IsHashIntervalTick(15, delta))
{
Building edifice = p.Position.GetEdifice(p.Map);
if (edifice != null && (!chairsOnly || (edifice.def.category == ThingCategory.Building && edifice.def.building.isSittable)))
{
GainComfortFromThingIfPossible(p, edifice, delta);
}
}
}
public static void GainComfortFromThingIfPossible(Pawn p, Thing from, int delta)
{
if (p.IsHashIntervalTick(15, delta))
{
float statValue = from.GetStatValue(StatDefOf.Comfort, applyPostProcess: true, 100);
if (statValue >= 0f && p.needs != null && p.needs.comfort != null)
{
p.needs.comfort.ComfortUsed(statValue);
}
}
}
public static float BodyResourceGrowthSpeed(Pawn pawn)
{
return pawn.needs?.food?.CurCategory.HungerMultiplier() ?? 1f;
}
public static bool FertileMateTarget(Pawn male, Pawn female)
{
if (female.gender != Gender.Female || female.Sterile())
{
return false;
}
CompEggLayer compEggLayer = female.TryGetComp<CompEggLayer>();
if (compEggLayer != null)
{
return !compEggLayer.FullyFertilized;
}
return true;
}
public static void Mated(Pawn male, Pawn female)
{
if (!female.Sterile() && !male.Sterile())
{
CompEggLayer compEggLayer = female.TryGetComp<CompEggLayer>();
if (compEggLayer != null)
{
compEggLayer.Fertilize(male);
}
else if (Rand.Value < 0.5f)
{
Hediff_Pregnant hediff_Pregnant = (Hediff_Pregnant)HediffMaker.MakeHediff(HediffDefOf.Pregnant, female);
hediff_Pregnant.SetParents(null, male, null);
female.health.AddHediff(hediff_Pregnant);
}
}
}
public static bool PlayerForcedJobNowOrSoon(Pawn pawn)
{
if (pawn.jobs == null)
{
return false;
}
Job curJob = pawn.CurJob;
if (curJob != null)
{
return curJob.playerForced;
}
if (pawn.jobs.jobQueue.Count > 0)
{
return pawn.jobs.jobQueue.Peek().job.playerForced;
}
return false;
}
public static bool TrySpawnHatchedOrBornPawn(Pawn pawn, Thing motherOrEgg, IntVec3? positionOverride = null)
{
if (motherOrEgg.SpawnedOrAnyParentSpawned)
{
return GenSpawn.Spawn(pawn, positionOverride ?? motherOrEgg.PositionHeld, motherOrEgg.MapHeld) != null;
}
if (motherOrEgg is Pawn pawn2)
{
if (pawn2.IsCaravanMember())
{
pawn2.GetCaravan().AddPawn(pawn, addCarriedPawnToWorldPawnsIfAny: true);
Find.WorldPawns.PassToWorld(pawn);
return true;
}
if (pawn2.IsWorldPawn())
{
Find.WorldPawns.PassToWorld(pawn);
return true;
}
}
else if (motherOrEgg.ParentHolder != null && motherOrEgg.ParentHolder is Pawn_InventoryTracker pawn_InventoryTracker)
{
if (pawn_InventoryTracker.pawn.IsCaravanMember())
{
pawn_InventoryTracker.pawn.GetCaravan().AddPawn(pawn, addCarriedPawnToWorldPawnsIfAny: true);
Find.WorldPawns.PassToWorld(pawn);
return true;
}
if (pawn_InventoryTracker.pawn.IsWorldPawn())
{
Find.WorldPawns.PassToWorld(pawn);
return true;
}
}
return false;
}
public static bool TryGetAvoidGrid(this Pawn p, out AvoidGrid grid, bool onlyIfLordAllows = true)
{
grid = null;
if (!p.Spawned)
{
return false;
}
if (p.Faction == null)
{
return false;
}
if (!p.Faction.def.canUseAvoidGrid)
{
return false;
}
if (p.Faction == Faction.OfPlayer || !p.Faction.HostileTo(Faction.OfPlayer))
{
return false;
}
if (p.kindDef.canUseAvoidGrid)
{
grid = p.Map.avoidGrid;
return true;
}
if (onlyIfLordAllows)
{
Lord lord = p.GetLord();
LordToil lordToil = lord?.CurLordToil;
if (lordToil != null && lordToil.useAvoidGrid)
{
grid = lord.Map.avoidGrid;
return true;
}
return false;
}
grid = p.Map.avoidGrid;
return true;
}
public static bool ShouldCollideWithPawns(Pawn p)
{
if (p == null || p.Downed || p.Dead)
{
return false;
}
if (p.IsShambler)
{
return true;
}
if (!p.mindState.anyCloseHostilesRecently)
{
return false;
}
if (p.IsPsychologicallyInvisible())
{
return false;
}
if (!p.kindDef.collidesWithPawns)
{
return false;
}
return true;
}
public static bool AnyPawnBlockingPathAt(IntVec3 c, Pawn forPawn, bool actAsIfHadCollideWithPawnsJob = false, bool collideOnlyWithStandingPawns = false, bool forPathFinder = false, bool useId = false)
{
return PawnBlockingPathAt(c, forPawn, actAsIfHadCollideWithPawnsJob, collideOnlyWithStandingPawns, forPathFinder, useId) != null;
}
public static Pawn PawnBlockingPathAt(IntVec3 c, Pawn forPawn, bool actAsIfHadCollideWithPawnsJob = false, bool collideOnlyWithStandingPawns = false, bool forPathFinder = false, bool useId = false)
{
List<Thing> thingList = c.GetThingList(forPawn.Map);
if (thingList.Count == 0)
{
return null;
}
bool collideWithNonHostile = false;
if (actAsIfHadCollideWithPawnsJob)
{
collideWithNonHostile = true;
}
else
{
Job curJob = forPawn.CurJob;
if (curJob != null && (curJob.collideWithPawns || curJob.def.collideWithPawns || forPawn.jobs.curDriver.collideWithPawns))
{
collideWithNonHostile = true;
}
}
for (int i = 0; i < thingList.Count; i++)
{
Pawn pawn = thingList[i] as Pawn;
if (PawnBlockedBy(forPawn, pawn, collideOnlyWithStandingPawns, collideWithNonHostile, forPathFinder, useId))
{
return pawn;
}
}
return null;
}
public static bool PawnBlockedBy(Pawn forPawn, Pawn other, bool collideOnlyWithStandingPawns = false, bool collideWithNonHostile = false, bool forPathFinder = false, bool useId = false)
{
if (!ShouldCollideWithPawns(other))
{
return false;
}
if (useId && forPawn.thingIDNumber < other.thingIDNumber && !other.stances.FullBodyBusyRecently)
{
return false;
}
if (other == forPawn)
{
return false;
}
if (collideOnlyWithStandingPawns)
{
if (other.pather.MovingNow)
{
return false;
}
if (other.pather.Moving && other.pather.MovedRecently(60))
{
return false;
}
}
if (PawnsCanShareCellBecauseOfBodySize(other, forPawn))
{
return false;
}
if (other.IsPsychologicallyInvisible())
{
return false;
}
if (!other.kindDef.collidesWithPawns)
{
return false;
}
if (other.HostileTo(forPawn))
{
return true;
}
if (forPawn.IsShambler && !MutantUtility.ShamblerShouldCollideWith(forPawn, other))
{
return false;
}
if (collideWithNonHostile)
{
if (!forPathFinder && forPawn.Drafted && other.RaceProps.Animal)
{
return false;
}
Job curJob = other.CurJob;
if (curJob != null && (curJob.collideWithPawns || curJob.def.collideWithPawns || other.jobs.curDriver.collideWithPawns))
{
return true;
}
}
return false;
}
private static bool PawnsCanShareCellBecauseOfBodySize(Pawn p1, Pawn p2)
{
float bodySize = p1.BodySize;
float bodySize2 = p2.BodySize;
if (bodySize >= 1.5f || bodySize2 >= 1.5f)
{
return false;
}
float num = bodySize / bodySize2;
if (num < 1f)
{
num = 1f / num;
}
return num > 3.57f;
}
public static bool KnownDangerAt(IntVec3 c, Map map, Pawn forPawn)
{
return c.GetEdifice(map)?.IsDangerousFor(forPawn) ?? false;
}
[Obsolete("Lord and job report display validation is now checked separately.")]
public static bool ShouldDisplayActionInInspectString(Pawn p)
{
if (p.Faction != Faction.OfPlayer && p.HostFaction != Faction.OfPlayer)
{
return false;
}
if (p.InMentalState)
{
return false;
}
if (p.IsMutant && p.mutant.Def.overrideInspectString)
{
return false;
}
return true;
}
public static bool ShouldDisplayLordReport(Pawn pawn)
{
if (ShouldShowCultistLordReport(pawn))
{
return true;
}
return ShouldShowActionReportToPlayer(pawn);
}
public static bool ShouldDisplayJobReport(Pawn pawn)
{
if (pawn.IsMutant && pawn.mutant.Def.overrideInspectString)
{
return false;
}
if (pawn.CurJobDef != null && pawn.CurJobDef.alwaysShowReport)
{
return true;
}
if (ModsConfig.AnomalyActive && pawn.Faction == Faction.OfHoraxCult && pawn.CurJobDef == JobDefOf.HateChanting)
{
return true;
}
if (ShouldShowCultistLordReport(pawn))
{
return true;
}
return ShouldShowActionReportToPlayer(pawn);
}
private static bool ShouldShowActionReportToPlayer(Pawn p)
{
if (p.Faction != Faction.OfPlayer && p.HostFaction != Faction.OfPlayer)
{
return false;
}
if (p.InMentalState)
{
return false;
}
if (p.IsMutant && p.mutant.Def.overrideInspectString)
{
return false;
}
return true;
}
public static bool ShouldDisplayFactionInInspectString(Pawn p)
{
if (p.IsMutant && p.mutant.Def.overrideInspectString)
{
return false;
}
return true;
}
private static bool ShouldShowCultistLordReport(Pawn pawn)
{
if (ModsConfig.AnomalyActive && pawn.Faction == Faction.OfHoraxCult && pawn.mindState.duty?.def == DutyDefOf.Invoke)
{
return true;
}
return false;
}
public static bool ShouldSendNotificationAbout(Pawn p)
{
if (Current.ProgramState != ProgramState.Playing)
{
return false;
}
if (p == null)
{
return false;
}
if (PawnGenerator.IsBeingGenerated(p))
{
return false;
}
if (p.IsWorldPawn() && (!p.IsCaravanMember() || !p.GetCaravan().IsPlayerControlled) && !IsTravelingInTransportPodWorldObject(p) && !p.IsBorrowedByAnyFaction() && p.Corpse.DestroyedOrNull())
{
return false;
}
if (p.IsSubhuman)
{
return false;
}
if (ModsConfig.AnomalyActive && p.Corpse is UnnaturalCorpse)
{
return false;
}
if (p.Faction != Faction.OfPlayer)
{
if (p.HostFaction != Faction.OfPlayer)
{
return false;
}
if (p.RaceProps.Humanlike && p.guest.Released && !p.Downed && !p.InBed())
{
return false;
}
if (p.CurJob != null && p.CurJob.exitMapOnArrival && !PrisonBreakUtility.IsPrisonBreaking(p))
{
return false;
}
if (IsExitingMap(p))
{
return false;
}
}
return true;
}
public static bool ShouldGetThoughtAbout(Pawn pawn, Pawn subject)
{
if (pawn.IsSubhuman || subject.IsSubhuman)
{
return false;
}
if (pawn.Faction != subject.Faction)
{
if (!subject.IsWorldPawn())
{
return !pawn.IsWorldPawn();
}
return false;
}
return true;
}
public static bool IsTeetotaler(this Pawn pawn)
{
if (!new HistoryEvent(HistoryEventDefOf.IngestedDrug, pawn.Named(HistoryEventArgsNames.Doer)).DoerWillingToDo())
{
return true;
}
if (!new HistoryEvent(HistoryEventDefOf.IngestedRecreationalDrug, pawn.Named(HistoryEventArgsNames.Doer)).DoerWillingToDo())
{
return true;
}
if (pawn.story != null)
{
return pawn.story.traits.DegreeOfTrait(TraitDefOf.DrugDesire) < 0;
}
return false;
}
public static bool CanTakeDrug(this Pawn pawn, ThingDef drug)
{
CompProperties_Drug compProperties = drug.GetCompProperties<CompProperties_Drug>();
if (compProperties == null)
{
return true;
}
if (CanTakeDrugForDependency(pawn, drug))
{
return true;
}
if (!compProperties.teetotalerCanConsume && pawn.IsTeetotaler())
{
return false;
}
if (ModsConfig.IdeologyActive)
{
if (!IdeoUtility.DoerWillingToDo(HistoryEventDefOf.IngestedDrug, pawn))
{
return false;
}
if (drug.IsNonMedicalDrug && !IdeoUtility.DoerWillingToDo(HistoryEventDefOf.IngestedRecreationalDrug, pawn))
{
return false;
}
if (drug.ingestible != null && drug.ingestible.drugCategory == DrugCategory.Hard && !IdeoUtility.DoerWillingToDo(HistoryEventDefOf.IngestedHardDrug, pawn))
{
return false;
}
}
return true;
}
public static bool CanTakeDrugForDependency(Pawn pawn, ThingDef drug)
{
if (!ModsConfig.BiotechActive || pawn.genes == null)
{
return false;
}
CompProperties_Drug compProperties = drug.GetCompProperties<CompProperties_Drug>();
if (compProperties == null)
{
return true;
}
foreach (Gene item in pawn.genes.GenesListForReading)
{
if (item is Gene_ChemicalDependency gene_ChemicalDependency && item.Active && gene_ChemicalDependency.def.chemical == compProperties.chemical)
{
return true;
}
}
return false;
}
public static bool TryGetChemicalDependencyGene(Pawn pawn, out Gene_ChemicalDependency gene)
{
gene = null;
if (!ModsConfig.BiotechActive || pawn.genes == null)
{
return false;
}
foreach (Gene item in pawn.genes.GenesListForReading)
{
if (item is Gene_ChemicalDependency gene_ChemicalDependency)
{
gene = gene_ChemicalDependency;
return true;
}
}
return false;
}
public static bool PawnWouldBeUnhappyTakingDrug(this Pawn pawn, ThingDef drug)
{
if (pawn.IsTeetotaler())
{
return drug.GetCompProperties<CompProperties_Drug>() != null;
}
return false;
}
public static bool IsProsthophobe(this Pawn pawn)
{
if (pawn.story != null)
{
return pawn.story.traits.HasTrait(TraitDefOf.BodyPurist);
}
return false;
}
public static bool IsPrisonerInPrisonCell(this Pawn pawn)
{
if (pawn.IsPrisoner && pawn.Spawned)
{
return pawn.Position.IsInPrisonCell(pawn.Map);
}
return false;
}
public static bool IsBeingArrested(Pawn pawn)
{
if (pawn.Map == null)
{
return false;
}
foreach (Pawn item in pawn.Map.mapPawns.AllPawnsSpawned)
{
if (item != pawn && item.CurJobDef == JobDefOf.Arrest && item.CurJob.AnyTargetIs(pawn))
{
return true;
}
}
return false;
}
public static string PawnKindsToCommaList(IEnumerable<Pawn> pawns, bool useAnd = false)
{
tmpPawns.Clear();
tmpPawns.AddRange(pawns);
if (tmpPawns.Count >= 2)
{
tmpPawns.SortBy((Pawn x) => !x.RaceProps.Humanlike, (Pawn x) => x.GetKindLabelPlural());
}
tmpAddedPawnKinds.Clear();
tmpPawnKindsStr.Clear();
for (int i = 0; i < tmpPawns.Count; i++)
{
if (tmpAddedPawnKinds.Contains(tmpPawns[i].kindDef))
{
continue;
}
tmpAddedPawnKinds.Add(tmpPawns[i].kindDef);
int num = 0;
for (int j = 0; j < tmpPawns.Count; j++)
{
if (tmpPawns[j].kindDef == tmpPawns[i].kindDef)
{
num++;
}
}
if (num == 1)
{
tmpPawnKindsStr.Add("1 " + tmpPawns[i].KindLabel);
}
else
{
tmpPawnKindsStr.Add(num + " " + tmpPawns[i].GetKindLabelPlural(num));
}
}
tmpPawns.Clear();
return tmpPawnKindsStr.ToCommaList(useAnd);
}
public static List<string> PawnKindsToList(IEnumerable<PawnKindDef> pawnKinds)
{
tmpPawnKinds.Clear();
tmpPawnKinds.AddRange(pawnKinds);
if (tmpPawnKinds.Count >= 2)
{
tmpPawnKinds.SortBy((PawnKindDef x) => !x.RaceProps.Humanlike, (PawnKindDef x) => GenLabel.BestKindLabel(x, Gender.None, plural: true));
}
tmpAddedPawnKinds.Clear();
tmpPawnKindsStr.Clear();
for (int i = 0; i < tmpPawnKinds.Count; i++)
{
if (tmpAddedPawnKinds.Contains(tmpPawnKinds[i]))
{
continue;
}
tmpAddedPawnKinds.Add(tmpPawnKinds[i]);
int num = 0;
for (int j = 0; j < tmpPawnKinds.Count; j++)
{
if (tmpPawnKinds[j] == tmpPawnKinds[i])
{
num++;
}
}
if (num == 1)
{
tmpPawnKindsStr.Add("1 " + GenLabel.BestKindLabel(tmpPawnKinds[i], Gender.None));
}
else
{
tmpPawnKindsStr.Add(num + " " + GenLabel.BestKindLabel(tmpPawnKinds[i], Gender.None, plural: true, num));
}
}
return tmpPawnKindsStr;
}
public static string PawnKindsToLineList(IEnumerable<PawnKindDef> pawnKinds, string prefix)
{
PawnKindsToList(pawnKinds);
return tmpPawnKindsStr.ToLineList(prefix);
}
public static string PawnKindsToLineList(IEnumerable<PawnKindDef> pawnKinds, string prefix, Color color)
{
PawnKindsToList(pawnKinds);
for (int i = 0; i < tmpPawnKindsStr.Count; i++)
{
tmpPawnKindsStr[i] = tmpPawnKindsStr[i].Colorize(color);
}
return tmpPawnKindsStr.ToLineList(prefix);
}
public static string PawnKindsToCommaList(IEnumerable<PawnKindDef> pawnKinds, bool useAnd = false)
{
PawnKindsToList(pawnKinds);
return tmpPawnKindsStr.ToCommaList(useAnd);
}
public static LocomotionUrgency ResolveLocomotion(Pawn pawn, LocomotionUrgency secondPriority)
{
if (!pawn.Dead && pawn.mindState.duty != null && pawn.mindState.duty.locomotion != 0)
{
return pawn.mindState.duty.locomotion;
}
return secondPriority;
}
public static LocomotionUrgency ResolveLocomotion(Pawn pawn, LocomotionUrgency secondPriority, LocomotionUrgency thirdPriority)
{
LocomotionUrgency locomotionUrgency = ResolveLocomotion(pawn, secondPriority);
if (locomotionUrgency != 0)
{
return locomotionUrgency;
}
return thirdPriority;
}
public static Danger ResolveMaxDanger(Pawn pawn, Danger secondPriority)
{
if (!pawn.Dead && pawn.mindState.duty != null && pawn.mindState.duty.maxDanger != 0)
{
return pawn.mindState.duty.maxDanger;
}
return secondPriority;
}
public static Danger ResolveMaxDanger(Pawn pawn, Danger secondPriority, Danger thirdPriority)
{
Danger danger = ResolveMaxDanger(pawn, secondPriority);
if (danger != 0)
{
return danger;
}
return thirdPriority;
}
public static bool IsPermanentCombatant(this Pawn pawn)
{
if (pawn?.mindState == null)
{
return true;
}
if (pawn.IsAnimal && pawn.Faction != null)
{
return false;
}
if (pawn.DevelopmentalStage.Juvenile())
{
return false;
}
return true;
}
public static bool IsCombatant(this Pawn pawn)
{
if (pawn.IsPermanentCombatant())
{
return true;
}
return pawn.mindState.CombatantRecently;
}
public static bool IsFighting(this Pawn pawn)
{
if (pawn.CurJob != null)
{
if (pawn.CurJob.def != JobDefOf.AttackMelee && pawn.CurJob.def != JobDefOf.AttackStatic && pawn.CurJob.def != JobDefOf.Wait_Combat && pawn.CurJob.def != JobDefOf.PredatorHunt)
{
return pawn.CurJob.def == JobDefOf.ManTurret;
}
return true;
}
return false;
}
public static bool IsAttacking(this Pawn pawn)
{
if (pawn.CurJobDef == JobDefOf.AttackMelee || pawn.CurJobDef == JobDefOf.AttackStatic)
{
return true;
}
if (pawn.CurJobDef == JobDefOf.Wait_Combat && pawn.stances.curStance is Stance_Busy stance_Busy && stance_Busy.focusTarg.IsValid)
{
return true;
}
return false;
}
public static Hediff_Psylink GetMainPsylinkSource(this Pawn pawn)
{
return (Hediff_Psylink)pawn.health.hediffSet.GetFirstHediffOfDef(HediffDefOf.PsychicAmplifier);
}
public static int GetPsylinkLevel(this Pawn pawn)
{
int num = 0;
foreach (Hediff hediff in pawn.health.hediffSet.hediffs)
{
if (hediff is Hediff_Psylink hediff_Psylink)
{
num += hediff_Psylink.level;
}
}
return num;
}
public static int GetMaxPsylinkLevel(this Pawn pawn)
{
return (int)HediffDefOf.PsychicAmplifier.maxSeverity;
}
public static RoyalTitle GetMaxPsylinkLevelTitle(this Pawn pawn)
{
if (pawn.royalty == null)
{
return null;
}
int num = 0;
RoyalTitle result = null;
foreach (RoyalTitle item in pawn.royalty.AllTitlesInEffectForReading)
{
if (num < item.def.maxPsylinkLevel)
{
num = item.def.maxPsylinkLevel;
result = item;
}
}
return result;
}
public static int GetMaxPsylinkLevelByTitle(this Pawn pawn)
{
return pawn.GetMaxPsylinkLevelTitle()?.def.maxPsylinkLevel ?? 0;
}
public static void ChangePsylinkLevel(this Pawn pawn, int levelOffset, bool sendLetter = true)
{
Hediff_Psylink mainPsylinkSource = pawn.GetMainPsylinkSource();
if (mainPsylinkSource == null)
{
mainPsylinkSource = (Hediff_Psylink)HediffMaker.MakeHediff(HediffDefOf.PsychicAmplifier, pawn);
try
{
mainPsylinkSource.suppressPostAddLetter = !sendLetter;
pawn.health.AddHediff(mainPsylinkSource, pawn.health.hediffSet.GetBrain());
return;
}
finally
{
mainPsylinkSource.suppressPostAddLetter = false;
}
}
mainPsylinkSource.ChangeLevel(levelOffset, sendLetter);
}
public static void GiveAllStartingPlayerPawnsThought(ThoughtDef thought)
{
foreach (Pawn startingAndOptionalPawn in Find.GameInitData.startingAndOptionalPawns)
{
if (startingAndOptionalPawn.needs.mood == null)
{
continue;
}
if (thought.IsSocial)
{
foreach (Pawn startingAndOptionalPawn2 in Find.GameInitData.startingAndOptionalPawns)
{
if (startingAndOptionalPawn2 != startingAndOptionalPawn)
{
startingAndOptionalPawn.needs.mood.thoughts.memories.TryGainMemory(thought, startingAndOptionalPawn2);
}
}
}
else
{
startingAndOptionalPawn.needs.mood.thoughts.memories.TryGainMemory(thought);
}
}
}
public static IntVec3 DutyLocation(this Pawn pawn)
{
Pawn_RopeTracker roping = pawn.roping;
if (roping != null && roping.IsRopedToSpot)
{
return pawn.roping.RopedToSpot;
}
if (pawn.mindState.duty != null && pawn.mindState.duty.focus.IsValid)
{
return pawn.mindState.duty.focus.Cell;
}
return pawn.Position;
}
public static bool EverBeenColonistOrTameAnimal(Pawn pawn)
{
return pawn.records.GetAsInt(RecordDefOf.TimeAsColonistOrColonyAnimal) > 0;
}
public static bool EverBeenPrisoner(Pawn pawn)
{
return pawn.records.GetAsInt(RecordDefOf.TimeAsPrisoner) > 0;
}
public static bool EverBeenQuestLodger(Pawn pawn)
{
return pawn.records.GetAsInt(RecordDefOf.TimeAsQuestLodger) > 0;
}
public static void RecoverFromUnwalkablePositionOrKill(IntVec3 c, Map map)
{
if (!c.InBounds(map) || c.Walkable(map))
{
return;
}
tmpThings.Clear();
tmpThings.AddRange(c.GetThingList(map));
for (int i = 0; i < tmpThings.Count; i++)
{
if (!(tmpThings[i] is Pawn pawn))
{
continue;
}
if (CellFinder.TryFindBestPawnStandCell(pawn, out var cell))
{
pawn.Position = cell;
pawn.Notify_Teleported(endCurrentJob: true, resetTweenedPos: false);
continue;
}
DamageInfo damageInfo = new DamageInfo(DamageDefOf.Crush, 99999f, 999f, -1f, null, pawn.health.hediffSet.GetBrain(), null, DamageInfo.SourceCategory.Collapse);
damageInfo.SetIgnoreInstantKillProtection(ignore: true);
pawn.TakeDamage(damageInfo);
if (!pawn.Dead)
{
pawn.Kill(damageInfo);
}
}
}
public static float GetManhunterOnDamageChance(Pawn pawn, Thing instigator = null, float distance = -1f)
{
float num = GetManhunterOnDamageChance(pawn.def);
if (pawn.health.hediffSet.HasHediff(HediffDefOf.Scaria))
{
num += 0.5f;
}
if (instigator != null)
{
num *= GenMath.LerpDoubleClamped(1f, 30f, 3f, 1f, distance);
num *= 1f - instigator.GetStatValue(StatDefOf.HuntingStealth);
if (instigator is Pawn instigator2)
{
num *= GetManhunterChanceFactorForInstigator(instigator2);
}
}
return Mathf.Clamp01(num);
}
public static float GetManhunterOnDamageChance(ThingDef def)
{
return def.race.manhunterOnDamageChance * Find.Storyteller.difficulty.manhunterChanceOnDamageFactor;
}
public static string GetManhunterOnDamageChanceExplanation(ThingDef def, Pawn pawn)
{
StringBuilder stringBuilder = new StringBuilder();
stringBuilder.AppendLine("HarmedRevengeChanceExplanation".Translate());
stringBuilder.AppendLine();
stringBuilder.AppendLine(def.LabelCap + ": " + def.race.manhunterOnDamageChance.ToStringPercent());
stringBuilder.AppendLine("StatsReport_DifficultyMultiplier".Translate(Find.Storyteller.difficultyDef.label) + ": " + Find.Storyteller.difficulty.manhunterChanceOnDamageFactor.ToStringPercent());
if (pawn != null && pawn.health.hediffSet.HasHediff(HediffDefOf.Scaria))
{
stringBuilder.AppendLine(HediffDefOf.Scaria.LabelCap + ": " + 0.5f.ToStringPercentSigned());
}
stringBuilder.AppendLine();
float f = ((pawn == null) ? GetManhunterOnDamageChance(def) : GetManhunterOnDamageChance(pawn));
stringBuilder.AppendLine("StatsReport_FinalValue".Translate() + ": " + f.ToStringPercent());
return stringBuilder.ToString();
}
public static float GetManhunterChanceFactorForInstigator(Pawn instigator)
{
if (ModsConfig.AnomalyActive && instigator?.Faction == Faction.OfEntities)
{
return 0f;
}
float num = 1f;
if (ModsConfig.IdeologyActive && instigator?.Ideo != null)
{
RoleEffect roleEffect = instigator.Ideo.GetRole(instigator)?.def.roleEffects?.FirstOrDefault((RoleEffect eff) => eff is RoleEffect_HuntingRevengeChanceFactor);
if (roleEffect != null)
{
num *= ((RoleEffect_HuntingRevengeChanceFactor)roleEffect).factor;
}
}
return num;
}
public static float GetManhunterOnTameFailChance(Pawn pawn)
{
return Mathf.Clamp01(GetManhunterOnTameFailChance(pawn.def));
}
public static float GetManhunterOnTameFailChance(ThingDef def)
{
return def.race.manhunterOnTameFailChance;
}
public static string GetManhunterOnTameFailChanceExplanation(ThingDef def, Pawn pawn)
{
StringBuilder stringBuilder = new StringBuilder();
stringBuilder.AppendLine("Stat_Race_Animal_TameFailedRevengeChance_Desc".Translate());
stringBuilder.AppendLine();
stringBuilder.AppendLine(def.LabelCap + ": " + def.race.manhunterOnTameFailChance.ToStringPercent());
stringBuilder.AppendLine();
float f = ((pawn == null) ? GetManhunterOnTameFailChance(def) : GetManhunterOnTameFailChance(pawn));
stringBuilder.AppendLine("StatsReport_FinalValue".Translate() + ": " + f.ToStringPercent());
return stringBuilder.ToString();
}
public static MentalStateDef ManhunterStateFor(Pawn pawn)
{
if (pawn.health.hediffSet.HasHediff(HediffDefOf.Scaria))
{
return MentalStateDefOf.ManhunterPermanent;
}
return MentalStateDefOf.Manhunter;
}
public static bool PlayerHasReproductivePair(PawnKindDef pawnKindDef)
{
if (!pawnKindDef.RaceProps.Animal)
{
return false;
}
List<Pawn> allMapsCaravansAndTravellingTransporters_Alive_OfPlayerFaction = PawnsFinder.AllMapsCaravansAndTravellingTransporters_Alive_OfPlayerFaction;
bool flag = false;
bool flag2 = false;
for (int i = 0; i < allMapsCaravansAndTravellingTransporters_Alive_OfPlayerFaction.Count; i++)
{
Pawn pawn = allMapsCaravansAndTravellingTransporters_Alive_OfPlayerFaction[i];
if (pawn.kindDef == pawnKindDef && pawn.ageTracker.CurLifeStage.reproductive)
{
if (pawn.gender == Gender.Male)
{
flag = true;
}
else if (pawn.gender == Gender.Female)
{
flag2 = true;
}
if (flag && flag2)
{
return true;
}
}
}
return false;
}
public static float PlayerAnimalBodySizePerCapita()
{
float num = 0f;
int num2 = 0;
List<Pawn> allMapsCaravansAndTravellingTransporters_Alive_OfPlayerFaction = PawnsFinder.AllMapsCaravansAndTravellingTransporters_Alive_OfPlayerFaction;
for (int i = 0; i < allMapsCaravansAndTravellingTransporters_Alive_OfPlayerFaction.Count; i++)
{
Pawn pawn = allMapsCaravansAndTravellingTransporters_Alive_OfPlayerFaction[i];
if (pawn.IsFreeColonist && !pawn.IsQuestLodger())
{
num2++;
}
if (pawn.IsAnimal)
{
num += pawn.BodySize;
}
}
if (num2 <= 0)
{
return 0f;
}
return num / (float)num2;
}
private static List<Pawn> PawnsOfFactionOnMapOrInCaravan(Pawn pawn)
{
if (pawn.Spawned)
{
return pawn.Map.mapPawns.SpawnedPawnsInFaction(pawn.Faction);
}
return pawn.GetCaravan()?.PawnsListForReading;
}
public static float PlayerVeneratedAnimalBodySizePerCapitaOnMapOrCaravan(Pawn pawn)
{
if (pawn.Ideo == null || pawn.Faction == null)
{
return 0f;
}
float num = 0f;
int num2 = 0;
List<Pawn> list = PawnsOfFactionOnMapOrInCaravan(pawn);
for (int i = 0; i < list.Count; i++)
{
if (list[i].Faction == pawn.Faction && !pawn.IsQuestLodger())
{
if (list[i].IsAnimal && pawn.Ideo.IsVeneratedAnimal(list[i]))
{
num += list[i].BodySize;
}
else if (list[i].RaceProps.Humanlike)
{
num2++;
}
}
}
return Mathf.Round(((num2 > 0) ? (num / (float)num2) : 0f) * 100f) / 100f;
}
public static Pawn FirstVeneratedAnimalOnMapOrCaravan(Pawn pawn)
{
if (pawn.Ideo == null || pawn.Faction == null)
{
return null;
}
List<Pawn> list = PawnsOfFactionOnMapOrInCaravan(pawn);
for (int i = 0; i < list.Count; i++)
{
if (pawn.Faction == list[i].Faction && pawn.Ideo.IsVeneratedAnimal(list[i]))
{
return list[i];
}
}
return null;
}
public static bool HasClothingNotRequiredByKind(Pawn p)
{
if (p.apparel == null)
{
return false;
}
List<Apparel> wornApparel = p.apparel.WornApparel;
if (wornApparel.Count > 0 && p.kindDef.apparelRequired.NullOrEmpty())
{
return true;
}
for (int i = 0; i < wornApparel.Count; i++)
{
Apparel apparel = wornApparel[i];
if (apparel.def.apparel.countsAsClothingForNudity && !p.kindDef.apparelRequired.Contains(apparel.def))
{
return true;
}
}
return false;
}
public static IEnumerable<PawnKindDef> GetCombatPawnKindsForPoints(Func<PawnKindDef, bool> selector, float points, Func<PawnKindDef, float> selectionWeight = null)
{
IEnumerable<PawnKindDef> allKinds = DefDatabase<PawnKindDef>.AllDefsListForReading.Where(selector);
if (selectionWeight == null)
{
selectionWeight = (PawnKindDef _) => 1f;
}
PawnKindDef result;
while (points > 0f && allKinds.Where((PawnKindDef def) => def.combatPower > 0f && def.combatPower <= points && def.appearsRandomlyInCombatGroups).TryRandomElementByWeight(selectionWeight, out result))
{
points -= result.combatPower;
yield return result;
}
}
public static int GetMaxAllowedToPickUp(Pawn pawn, ThingDef thingDef)
{
int maxAllowedToPickUp = GetMaxAllowedToPickUp(thingDef, pawn.Map);
if (maxAllowedToPickUp <= 0)
{
return 0;
}
int num = pawn.inventory.Count((Thing t) => t.def.orderedTakeGroup == thingDef.orderedTakeGroup);
return Math.Max(maxAllowedToPickUp - num, 0);
}
public static int GetMaxAllowedToPickUp(ThingDef thingDef, Map map = null)
{
if (map != null && !map.IsPlayerHome)
{
return int.MaxValue;
}
if (thingDef.orderedTakeGroup == null)
{
return 0;
}
return thingDef.orderedTakeGroup.max;
}
public static bool CanPickUp(Pawn pawn, ThingDef thingDef)
{
if (!pawn.Map.IsPlayerHome)
{
return true;
}
if (pawn.inventory != null && thingDef.orderedTakeGroup != null)
{
return thingDef.orderedTakeGroup.max > 0;
}
return false;
}
public static bool ShouldBeSlaughtered(this Pawn pawn)
{
if (!pawn.Spawned || !pawn.IsAnimal)
{
return false;
}
if (pawn.Map.designationManager.DesignationOn(pawn, DesignationDefOf.Slaughter) != null || pawn.Map.autoSlaughterManager.AnimalsToSlaughter.Contains(pawn))
{
return pawn.Map.designationManager.DesignationOn(pawn, DesignationDefOf.ReleaseAnimalToWild) == null;
}
return false;
}
public static bool CanBeBuried(this Thing t)
{
if (t is Corpse { MapHeld: not null } corpse)
{
return corpse.MapHeld.designationManager.DesignationOn(corpse, DesignationDefOf.ExtractSkull) == null;
}
return true;
}
public static bool PawnHadFuneral(Pawn pawn)
{
Precept_Ritual precept_Ritual = (Precept_Ritual)(pawn.ideo?.Ideo?.GetPrecept(PreceptDefOf.Funeral));
if (precept_Ritual != null && !precept_Ritual.completedObligations.NullOrEmpty())
{
return precept_Ritual.completedObligations.Any((RitualObligation o) => o.FirstValidTarget.Thing == pawn);
}
return false;
}
public static bool IsBiologicallyOrArtificiallyBlind(Pawn pawn)
{
if (!IsBiologicallyBlind(pawn))
{
return IsArtificiallyBlind(pawn);
}
return true;
}
public static bool IsBiologicallyBlind(Pawn pawn)
{
return !pawn.health.capacities.CapableOf(PawnCapacityDefOf.Sight);
}
public static bool IsArtificiallyBlind(Pawn p)
{
if (IsBiologicallyBlind(p))
{
return false;
}
if (p.apparel != null)
{
foreach (Apparel item in p.apparel.WornApparel)
{
if (item.def.apparel.blocksVision)
{
return true;
}
}
}
return false;
}
public static bool IsWorkTypeDisabledByAge(this Pawn pawn, WorkTypeDef workType, out int minAgeRequired)
{
for (int i = 0; i < pawn.RaceProps.lifeStageWorkSettings.Count; i++)
{
LifeStageWorkSettings lifeStageWorkSettings = pawn.RaceProps.lifeStageWorkSettings[i];
if (lifeStageWorkSettings.workType == workType && lifeStageWorkSettings.IsDisabled(pawn))
{
minAgeRequired = lifeStageWorkSettings.minAge;
return true;
}
}
minAgeRequired = 0;
return false;
}
public static bool DutyActiveWhenDown(this Pawn pawn, bool onlyInBed = false)
{
if (onlyInBed && !pawn.InBed())
{
return false;
}
return (pawn.GetLord()?.LordJob?.DutyActiveWhenDown(pawn)).GetValueOrDefault();
}
public static bool IsExitingMap(Pawn pawn)
{
Lord lord = pawn.GetLord();
if (lord == null)
{
return false;
}
if (!(lord.LordJob is LordJob_ExitMapBest) && !(lord.LordJob is LordJob_ExitMapNear) && !(lord.LordJob is LordJob_ExitOnShuttle))
{
return lord.LordJob is LordJob_TravelAndExit;
}
return true;
}
public static void ForceEjectFromContainer(Pawn pawn)
{
Thing resultingThing;
if (pawn.ParentHolder is Pawn_CarryTracker pawn_CarryTracker)
{
pawn_CarryTracker.TryDropCarriedThing(pawn_CarryTracker.pawn.Position, ThingPlaceMode.Near, out resultingThing);
pawn_CarryTracker.pawn.jobs.EndCurrentJob(JobCondition.InterruptForced);
}
if (pawn.ParentHolder is Building_Enterable building_Enterable)
{
building_Enterable.innerContainer.TryDrop(pawn, building_Enterable.InteractionCell, building_Enterable.Map, ThingPlaceMode.Near, out resultingThing);
}
if (pawn.ParentHolder is Building_Casket building_Casket)
{
building_Casket.EjectContents();
}
if (pawn.ParentHolder is Building_HoldingPlatform building_HoldingPlatform)
{
building_HoldingPlatform.EjectContents();
}
if (pawn.ParentHolder is CompBiosculpterPod compBiosculpterPod)
{
compBiosculpterPod.EjectContents(interrupted: true, playSounds: true);
}
}
}
```