根据向量相似度分析,与 'WorkGiver_Scanner' 最相关的代码定义如下: --- **文件路径 (精确匹配):** `C:\Steam\steamapps\common\RimWorld\Data\dll1.6\RimWorld\WorkGiver_Scanner.txt` ```csharp public abstract class WorkGiver_Scanner : WorkGiver { public virtual ThingRequest PotentialWorkThingRequest => ThingRequest.ForGroup(ThingRequestGroup.Undefined); public virtual int MaxRegionsToScanBeforeGlobalSearch => -1; public virtual bool Prioritized => false; public virtual bool AllowUnreachable => false; public virtual PathEndMode PathEndMode => PathEndMode.Touch; public virtual IEnumerable PotentialWorkCellsGlobal(Pawn pawn) { return Enumerable.Empty(); } public virtual IEnumerable PotentialWorkThingsGlobal(Pawn pawn) { return null; } public virtual Danger MaxPathDanger(Pawn pawn) { return pawn.NormalMaxDanger(); } public virtual bool HasJobOnThing(Pawn pawn, Thing t, bool forced = false) { return JobOnThing(pawn, t, forced) != null; } public virtual string JobInfo(Pawn pawn, Job job) { return string.Empty; } public virtual Job JobOnThing(Pawn pawn, Thing t, bool forced = false) { return null; } public virtual bool HasJobOnCell(Pawn pawn, IntVec3 c, bool forced = false) { return JobOnCell(pawn, c, forced) != null; } public virtual Job JobOnCell(Pawn pawn, IntVec3 cell, bool forced = false) { return null; } public virtual float GetPriority(Pawn pawn, TargetInfo t) { return 0f; } public virtual string PostProcessedGerund(Job job) { return def.gerund; } public float GetPriority(Pawn pawn, IntVec3 cell) { return GetPriority(pawn, new TargetInfo(cell, pawn.Map)); } public virtual ReservationLayerDef GetReservationLayer(Pawn pawn, LocalTargetInfo target) { return null; } } ``` --- **文件路径:** `C:\Steam\steamapps\common\RimWorld\Data\dll1.6\RimWorld\WorkGiver_HaulToSubcoreScanner.txt` **相似度:** 0.5742 ```csharp public class WorkGiver_HaulToSubcoreScanner : WorkGiver_Scanner { public override ThingRequest PotentialWorkThingRequest => ThingRequest.ForGroup(ThingRequestGroup.SubcoreScanner); public override bool HasJobOnThing(Pawn pawn, Thing t, bool forced = false) { if (!ModLister.CheckBiotech("Haul to subcore scanner")) { return false; } if (!(t is Building_SubcoreScanner { State: SubcoreScannerState.WaitingForIngredients } building_SubcoreScanner)) { return false; } if (!pawn.CanReserve(t, 1, -1, null, forced)) { return false; } return FindIngredients(pawn, building_SubcoreScanner).Thing != null; } public override Job JobOnThing(Pawn pawn, Thing t, bool forced = false) { if (!(t is Building_SubcoreScanner { State: SubcoreScannerState.WaitingForIngredients } building_SubcoreScanner)) { return null; } ThingCount thingCount = FindIngredients(pawn, building_SubcoreScanner); if (thingCount.Thing != null) { Job job = HaulAIUtility.HaulToContainerJob(pawn, thingCount.Thing, t); job.count = Mathf.Min(job.count, thingCount.Count); return job; } return null; } private ThingCount FindIngredients(Pawn pawn, Building_SubcoreScanner scanner) { Thing thing = GenClosest.ClosestThingReachable(pawn.Position, pawn.Map, ThingRequest.ForGroup(ThingRequestGroup.HaulableEver), PathEndMode.ClosestTouch, TraverseParms.For(pawn), 9999f, Validator); if (thing == null) { return default(ThingCount); } int requiredCountOf = scanner.GetRequiredCountOf(thing.def); return new ThingCount(thing, Mathf.Min(thing.stackCount, requiredCountOf)); bool Validator(Thing x) { if (!pawn.CanReserve(x)) { return false; } if (x.IsForbidden(pawn)) { return false; } return scanner.CanAcceptIngredient(x); } } } ``` --- **文件路径:** `C:\Steam\steamapps\common\RimWorld\Data\dll1.6\RimWorld\WorkGiver_HaulToBiosculpterPod.txt` **相似度:** 0.5453 ```csharp public class WorkGiver_HaulToBiosculpterPod : WorkGiver_Scanner { public override ThingRequest PotentialWorkThingRequest => ThingRequest.ForDef(ThingDefOf.BiosculpterPod); public override PathEndMode PathEndMode => PathEndMode.Touch; public override bool HasJobOnThing(Pawn pawn, Thing t, bool forced = false) { if (!ModLister.CheckIdeology("Biosculpting")) { return false; } if (!pawn.CanReserve(t, 1, -1, null, forced)) { return false; } if (pawn.Map.designationManager.DesignationOn(t, DesignationDefOf.Deconstruct) != null) { return false; } CompBiosculpterPod compBiosculpterPod = t.TryGetComp(); if (compBiosculpterPod == null || !compBiosculpterPod.PowerOn || compBiosculpterPod.State != 0 || (!forced && !compBiosculpterPod.autoLoadNutrition)) { return false; } if (t.IsBurning()) { return false; } if (compBiosculpterPod.RequiredNutritionRemaining > 0f) { if (FindNutrition(pawn, compBiosculpterPod).Thing == null) { JobFailReason.Is("NoFood".Translate()); return false; } return true; } return false; } public override Job JobOnThing(Pawn pawn, Thing t, bool forced = false) { CompBiosculpterPod compBiosculpterPod = t.TryGetComp(); if (compBiosculpterPod == null) { return null; } if (compBiosculpterPod.RequiredNutritionRemaining > 0f) { ThingCount thingCount = FindNutrition(pawn, compBiosculpterPod); if (thingCount.Thing != null) { Job job = HaulAIUtility.HaulToContainerJob(pawn, thingCount.Thing, t); job.count = Mathf.Min(job.count, thingCount.Count); return job; } } return null; } private ThingCount FindNutrition(Pawn pawn, CompBiosculpterPod pod) { Thing thing = GenClosest.ClosestThingReachable(pawn.Position, pawn.Map, ThingRequest.ForGroup(ThingRequestGroup.FoodSourceNotPlantOrTree), PathEndMode.ClosestTouch, TraverseParms.For(pawn), 9999f, Validator); if (thing == null) { return default(ThingCount); } int b = Mathf.CeilToInt(pod.RequiredNutritionRemaining / thing.GetStatValue(StatDefOf.Nutrition)); return new ThingCount(thing, Mathf.Min(thing.stackCount, b)); bool Validator(Thing x) { if (x.IsForbidden(pawn) || !pawn.CanReserve(x)) { return false; } if (!pod.CanAcceptNutrition(x)) { return false; } return true; } } } ``` --- **文件路径:** `C:\Steam\steamapps\common\RimWorld\Data\dll1.6\RimWorld\WorkGiver_ConstructFinishFrames.txt` **相似度:** 0.5184 ```csharp public class WorkGiver_ConstructFinishFrames : WorkGiver_Scanner { public override PathEndMode PathEndMode => PathEndMode.Touch; public override ThingRequest PotentialWorkThingRequest => ThingRequest.ForGroup(ThingRequestGroup.BuildingFrame); public override Danger MaxPathDanger(Pawn pawn) { return Danger.Deadly; } public override Job JobOnThing(Pawn pawn, Thing t, bool forced = false) { if (t.Faction != pawn.Faction) { return null; } if (!(t is Frame frame)) { return null; } if (!frame.IsCompleted()) { return null; } if (!GenConstruct.CanTouchTargetFromValidCell(frame, pawn)) { return null; } if (GenConstruct.FirstBlockingThing(frame, pawn) != null) { return GenConstruct.HandleBlockingThingJob(frame, pawn, forced); } if (!GenConstruct.CanConstruct(frame, pawn, checkSkills: true, forced)) { return null; } return JobMaker.MakeJob(JobDefOf.FinishFrame, frame); } } ``` --- **文件路径:** `C:\Steam\steamapps\common\RimWorld\Data\dll1.6\RimWorld\WorkGiver_CookFillHopper.txt` **相似度:** 0.5093 ```csharp public class WorkGiver_CookFillHopper : WorkGiver_Scanner { private static string TheOnlyAvailableFoodIsInStorageOfHigherPriorityTrans; private static string NoFoodToFillHopperTrans; public override ThingRequest PotentialWorkThingRequest => ThingRequest.ForDef(ThingDefOf.Hopper); public override PathEndMode PathEndMode => PathEndMode.ClosestTouch; public WorkGiver_CookFillHopper() { if (TheOnlyAvailableFoodIsInStorageOfHigherPriorityTrans == null) { TheOnlyAvailableFoodIsInStorageOfHigherPriorityTrans = "TheOnlyAvailableFoodIsInStorageOfHigherPriority".Translate(); } if (NoFoodToFillHopperTrans == null) { NoFoodToFillHopperTrans = "NoFoodToFillHopper".Translate(); } } public override Job JobOnThing(Pawn pawn, Thing thing, bool forced = false) { if (!(thing is ISlotGroupParent hopperSgp)) { return null; } if (!pawn.CanReserve(thing.Position)) { return null; } float num = 0f; List list = pawn.Map.thingGrid.ThingsListAt(thing.Position); for (int i = 0; i < list.Count; i++) { Thing thing2 = list[i]; if (Building_NutrientPasteDispenser.IsAcceptableFeedstock(thing2.def)) { num = (float)thing2.stackCount / (float)thing2.def.stackLimit; } } if (num > 0.35f) { JobFailReason.Is("AlreadyFilledLower".Translate()); return null; } return HopperFillFoodJob(pawn, hopperSgp, forced); } public static Job HopperFillFoodJob(Pawn pawn, ISlotGroupParent hopperSgp, bool forced) { Building building = (Building)hopperSgp; if (!pawn.CanReserveAndReach(building.Position, PathEndMode.Touch, pawn.NormalMaxDanger())) { return null; } ThingDef thingDef = null; Thing firstItem = building.Position.GetFirstItem(building.Map); if (firstItem != null) { if (!Building_NutrientPasteDispenser.IsAcceptableFeedstock(firstItem.def)) { if (firstItem.IsForbidden(pawn)) { return null; } return HaulAIUtility.HaulAsideJobFor(pawn, firstItem); } thingDef = firstItem.def; } List list = ((thingDef != null) ? pawn.Map.listerThings.ThingsOfDef(thingDef) : pawn.Map.listerThings.ThingsInGroup(ThingRequestGroup.FoodSourceNotPlantOrTree)); bool flag = false; for (int i = 0; i < list.Count; i++) { Thing thing = list[i]; if (!thing.def.IsNutritionGivingIngestible || (thing.def.ingestible.preferability != FoodPreferability.RawBad && thing.def.ingestible.preferability != FoodPreferability.RawTasty) || !HaulAIUtility.PawnCanAutomaticallyHaul(pawn, thing, forced) || !pawn.Map.haulDestinationManager.SlotGroupAt(building.Position).Settings.AllowedToAccept(thing)) { continue; } if ((int)StoreUtility.CurrentStoragePriorityOf(thing, forced) >= (int)hopperSgp.GetSlotGroup().Settings.Priority) { flag = true; JobFailReason.Is(TheOnlyAvailableFoodIsInStorageOfHigherPriorityTrans); continue; } Job job = HaulAIUtility.HaulToCellStorageJob(pawn, thing, building.Position, fitInStoreCell: true); if (job != null) { return job; } } if (!flag) { JobFailReason.Is(NoFoodToFillHopperTrans); } return null; } } ``` --- **文件路径:** `C:\Steam\steamapps\common\RimWorld\Data\dll1.6\RimWorld\WorkGiver_InteractAnimal.txt` **相似度:** 0.5082 ```csharp public abstract class WorkGiver_InteractAnimal : WorkGiver_Scanner { protected static string NoUsableFoodTrans; protected static string AnimalInteractedTooRecentlyTrans; private static string CantInteractAnimalDownedTrans; private static string CantInteractAnimalAsleepTrans; private static string CantInteractAnimalBusyTrans; protected bool canInteractWhileSleeping; public override PathEndMode PathEndMode => PathEndMode.OnCell; public static void ResetStaticData() { NoUsableFoodTrans = "NoUsableFood".Translate(); AnimalInteractedTooRecentlyTrans = "AnimalInteractedTooRecently".Translate(); CantInteractAnimalDownedTrans = "CantInteractAnimalDowned".Translate(); CantInteractAnimalAsleepTrans = "CantInteractAnimalAsleep".Translate(); CantInteractAnimalBusyTrans = "CantInteractAnimalBusy".Translate(); } protected virtual bool CanInteractWithAnimal(Pawn pawn, Pawn animal, bool forced) { if (CanInteractWithAnimal(pawn, animal, out var jobFailReason, forced, canInteractWhileSleeping)) { return true; } if (jobFailReason != null) { JobFailReason.Is(jobFailReason); } return false; } public static bool CanInteractWithAnimal(Pawn pawn, Pawn animal, out string jobFailReason, bool forced, bool canInteractWhileSleeping = false, bool ignoreSkillRequirements = false, bool canInteractWhileRoaming = false) { jobFailReason = null; if (!pawn.CanReserve(animal, 1, -1, null, forced)) { return false; } if (animal.Downed) { jobFailReason = CantInteractAnimalDownedTrans; return false; } if (!animal.Awake() && !canInteractWhileSleeping) { jobFailReason = CantInteractAnimalAsleepTrans; return false; } if (!animal.CanCasuallyInteractNow(twoWayInteraction: false, canInteractWhileSleeping, canInteractWhileRoaming)) { jobFailReason = CantInteractAnimalBusyTrans; return false; } int num = TrainableUtility.MinimumHandlingSkill(animal); if (!ignoreSkillRequirements && num > pawn.skills.GetSkill(SkillDefOf.Animals).Level) { jobFailReason = "AnimalsSkillTooLow".Translate(num); return false; } return true; } protected bool HasFoodToInteractAnimal(Pawn pawn, Pawn tamee) { ThingOwner innerContainer = pawn.inventory.innerContainer; int num = 0; float num2 = JobDriver_InteractAnimal.RequiredNutritionPerFeed(tamee); float num3 = 0f; for (int i = 0; i < innerContainer.Count; i++) { Thing thing = innerContainer[i]; if (!tamee.WillEat(thing, pawn) || (int)thing.def.ingestible.preferability > 5 || thing.def.IsDrug) { continue; } for (int j = 0; j < thing.stackCount; j++) { num3 += thing.GetStatValue(StatDefOf.Nutrition); if (num3 >= num2) { num++; num3 = 0f; } if (num >= 2) { return true; } } } return false; } protected Job TakeFoodForAnimalInteractJob(Pawn pawn, Pawn tamee) { ThingDef foodDef; Thing thing = FoodUtility.BestFoodSourceOnMap(pawn, tamee, desperate: false, out foodDef, FoodPreferability.RawTasty, allowPlant: false, allowDrug: false, allowCorpse: false, allowDispenserFull: false, allowDispenserEmpty: false, allowForbidden: false, allowSociallyImproper: false, allowHarvest: false, forceScanWholeMap: false, ignoreReservations: false, calculateWantedStackCount: false, FoodPreferability.Undefined, JobDriver_InteractAnimal.RequiredNutritionPerFeed(tamee) * 2f * 4f); if (thing == null) { return null; } float wantedNutrition = JobDriver_InteractAnimal.RequiredNutritionPerFeed(tamee) * 2f * 4f; float nutrition = FoodUtility.GetNutrition(tamee, thing, foodDef); int count = FoodUtility.StackCountForNutrition(wantedNutrition, nutrition); Job job = JobMaker.MakeJob(JobDefOf.TakeInventory, thing); job.count = count; return job; } } ```