public static Job HaulToStorageJob(Pawn p, Thing t) { StoragePriority currentPriority = HaulAIUtility.StoragePriorityAtFor(t.Position, t); IntVec3 storeCell = default(IntVec3); if (!StoreUtility.TryFindBestBetterStoreCellFor(t, p, p.Map, currentPriority, p.Faction, out storeCell, true)) { JobFailReason.Is(HaulAIUtility.NoEmptyPlaceLowerTrans); return(null); } return(HaulAIUtility.HaulMaxNumToCellJob(p, t, storeCell, false)); }
public static Job HaulAsideJobFor(Pawn p, Thing t) { IntVec3 c; if (!HaulAIUtility.CanHaulAside(p, t, out c)) { return(null); } return(new Job(JobDefOf.HaulToCell, t, c) { count = 99999, haulOpportunisticDuplicates = false, haulMode = HaulMode.ToCellNonStorage, ignoreDesignations = true }); }
internal bool <> m__1(Region r) { HaulAIUtility.candidates.Clear(); HaulAIUtility.candidates.AddRange(r.Cells); HaulAIUtility.candidates.Sort((IntVec3 a, IntVec3 b) => a.DistanceToSquared(this.center).CompareTo(b.DistanceToSquared(this.center))); for (int i = 0; i < HaulAIUtility.candidates.Count; i++) { IntVec3 c = HaulAIUtility.candidates[i]; if (HaulAIUtility.HaulablePlaceValidator(this.haulable, this.worker, c)) { this.foundCell = c; return(true); } } return(false); }
public static Job HaulAsideJobFor(Pawn p, Thing t) { IntVec3 c = default(IntVec3); if (!HaulAIUtility.CanHaulAside(p, t, out c)) { return(null); } Job job = new Job(JobDefOf.HaulToCell, t, c); job.count = 99999; job.haulOpportunisticDuplicates = false; job.haulMode = HaulMode.ToCellNonStorage; job.ignoreDesignations = true; return(job); }
private static bool TryFindSpotToPlaceHaulableCloseTo(Thing haulable, Pawn worker, IntVec3 center, out IntVec3 spot) { Region region = center.GetRegion(worker.Map, RegionType.Set_Passable); bool result; if (region == null) { spot = center; result = false; } else { TraverseParms traverseParms = TraverseParms.For(worker, Danger.Deadly, TraverseMode.ByPawn, false); IntVec3 foundCell = IntVec3.Invalid; RegionTraverser.BreadthFirstTraverse(region, (Region from, Region r) => r.Allows(traverseParms, false), delegate(Region r) { HaulAIUtility.candidates.Clear(); HaulAIUtility.candidates.AddRange(r.Cells); HaulAIUtility.candidates.Sort((IntVec3 a, IntVec3 b) => a.DistanceToSquared(center).CompareTo(b.DistanceToSquared(center))); for (int i = 0; i < HaulAIUtility.candidates.Count; i++) { IntVec3 intVec = HaulAIUtility.candidates[i]; if (HaulAIUtility.HaulablePlaceValidator(haulable, worker, intVec)) { foundCell = intVec; return(true); } } return(false); }, 100, RegionType.Set_Passable); if (foundCell.IsValid) { spot = foundCell; result = true; } else { spot = center; result = false; } } return(result); }
public static bool CanHaulAside(Pawn p, Thing t, out IntVec3 storeCell) { storeCell = IntVec3.Invalid; if (!t.def.EverHaulable) { return(false); } if (t.IsBurning()) { return(false); } if (!p.CanReserveAndReach(t, PathEndMode.ClosestTouch, p.NormalMaxDanger(), 1, -1, null, false)) { return(false); } if (!HaulAIUtility.TryFindSpotToPlaceHaulableCloseTo(t, p, t.PositionHeld, out storeCell)) { return(false); } return(true); }
public static Job HaulToStorageJob(Pawn p, Thing t) { StoragePriority currentPriority = StoreUtility.CurrentStoragePriorityOf(t); IntVec3 storeCell; IHaulDestination haulDestination; if (!StoreUtility.TryFindBestBetterStorageFor(t, p, p.Map, currentPriority, p.Faction, out storeCell, out haulDestination, true)) { JobFailReason.Is(HaulAIUtility.NoEmptyPlaceLowerTrans, null); return(null); } if (haulDestination is ISlotGroupParent) { return(HaulAIUtility.HaulToCellStorageJob(p, t, storeCell, false)); } Thing thing = haulDestination as Thing; if (thing != null && thing.TryGetInnerInteractableThingOwner() != null) { return(HaulAIUtility.HaulToContainerJob(p, t, thing)); } Log.Error("Don't know how to handle HaulToStorageJob for storage " + haulDestination.ToStringSafe <IHaulDestination>() + ". thing=" + t.ToStringSafe <Thing>(), false); return(null); }
public static bool PawnCanAutomaticallyHaul(Pawn p, Thing t, bool forced) { if (!t.def.EverHaulable) { return(false); } if (t.IsForbidden(p)) { if (!t.Position.InAllowedArea(p)) { JobFailReason.Is(HaulAIUtility.ForbiddenOutsideAllowedAreaLowerTrans, null); } else { JobFailReason.Is(HaulAIUtility.ForbiddenLowerTrans, null); } return(false); } return((t.def.alwaysHaulable || t.Map.designationManager.DesignationOn(t, DesignationDefOf.Haul) != null || t.IsInValidStorage()) && HaulAIUtility.PawnCanAutomaticallyHaulFast(p, t, forced)); }
public Job TryOpportunisticJob(Job job) { Job result; if (this.pawn.def.race.intelligence < Intelligence.Humanlike) { result = null; } else if (this.pawn.Faction != Faction.OfPlayer) { result = null; } else if (this.pawn.Drafted) { result = null; } else if (job.playerForced) { result = null; } else if (this.pawn.RaceProps.intelligence < Intelligence.Humanlike) { result = null; } else if (!job.def.allowOpportunisticPrefix) { result = null; } else if (this.pawn.story.WorkTagIsDisabled(WorkTags.ManualDumb | WorkTags.Hauling)) { result = null; } else if (this.pawn.InMentalState) { result = null; } else { IntVec3 cell = job.targetA.Cell; if (!cell.IsValid) { result = null; } else { float num = this.pawn.Position.DistanceTo(cell); if (num < AITuning.OpportunisticJobMinDistPawnToDest) { result = null; } else { List <Thing> list = this.pawn.Map.listerHaulables.ThingsPotentiallyNeedingHauling(); for (int i = 0; i < list.Count; i++) { Thing thing = list[i]; if (this.pawn.Map.reservationManager.FirstRespectedReserver(thing, this.pawn) == null) { float num2 = this.pawn.Position.DistanceTo(thing.Position); if (num2 <= AITuning.OpportunisticJobMaxDistPawnToItem) { if (num2 <= num * AITuning.OpportunisticJobMaxPickupDistanceFactor) { if (num2 + thing.Position.DistanceTo(cell) <= num * AITuning.OpportunisticJobMaxRatioOppHaulDistanceToDestDistance) { if (HaulAIUtility.PawnCanAutomaticallyHaulFast(this.pawn, thing, false)) { StoragePriority currentPriority = StoreUtility.CurrentStoragePriorityOf(thing); IntVec3 invalid = IntVec3.Invalid; if (StoreUtility.TryFindBestBetterStoreCellFor(thing, this.pawn, this.pawn.Map, currentPriority, this.pawn.Faction, out invalid, true)) { float num3 = invalid.DistanceTo(cell); if (num3 <= AITuning.OpportunisticJobMaxDistDestToDropoff) { if (num3 <= num * AITuning.OpportunisticJobMaxDistDestToDropoffFactor) { if (num2 + thing.Position.DistanceTo(invalid) + num3 <= num * AITuning.OpportunisticJobMaxRatioOppHaulDistanceToDestDistance) { if (num2 + num3 <= num) { if (this.pawn.Position.WithinRegions(thing.Position, this.pawn.Map, AITuning.OpportunisticJobMaxPickupRegions, TraverseParms.For(this.pawn, Danger.Deadly, TraverseMode.ByPawn, false), RegionType.Set_Passable)) { if (invalid.WithinRegions(cell, this.pawn.Map, AITuning.OpportunisticJobMaxDropoffRegions, TraverseParms.For(this.pawn, Danger.Deadly, TraverseMode.ByPawn, false), RegionType.Set_Passable)) { if (DebugViewSettings.drawOpportunisticJobs) { Log.Message("Opportunistic job spawned", false); this.pawn.Map.debugDrawer.FlashLine(this.pawn.Position, thing.Position, 600, SimpleColor.Red); this.pawn.Map.debugDrawer.FlashLine(thing.Position, invalid, 600, SimpleColor.Green); this.pawn.Map.debugDrawer.FlashLine(invalid, cell, 600, SimpleColor.Blue); } return(HaulAIUtility.HaulToCellStorageJob(this.pawn, thing, invalid, false)); } } } } } } } } } } } } } result = null; } } } return(result); }
public static bool PawnCanAutomaticallyHaulFast(Pawn p, Thing t, bool forced) { return(HaulAIUtility.PawnCanAutomaticallyHaulBasicChecks(p, t, forced)); }
public static Toil PlaceHauledThingInCell(TargetIndex cellInd, Toil nextToilOnPlaceFailOrIncomplete, bool storageMode, bool tryStoreInSameStorageIfSpotCantHoldWholeStack = false) { Toil toil = new Toil(); 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(string.Concat(actor, " 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.RefuelAtomic || curJob.def == JobDefOf.RearmTurretAtomic) { placedAction = delegate(Thing th, int added) { if (curJob.placedThings == null) { curJob.placedThings = new List <ThingCountClass>(); } ThingCountClass thingCountClass = curJob.placedThings.Find((ThingCountClass x) => x.thing == th); if (thingCountClass != null) { thingCountClass.Count += added; } else { curJob.placedThings.Add(new ThingCountClass(th, added)); } }; } if (!actor.carryTracker.TryDropCarriedThing(cell, ThingPlaceMode.Direct, out var _, placedAction)) { if (storageMode) { if (nextToilOnPlaceFailOrIncomplete != null && ((tryStoreInSameStorageIfSpotCantHoldWholeStack && StoreUtility.TryFindBestBetterStoreCellForIn(actor.carryTracker.CarriedThing, actor, actor.Map, StoragePriority.Unstored, actor.Faction, cell.GetSlotGroup(actor.Map), 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 { Job job = HaulAIUtility.HaulAsideJobFor(actor, actor.carryTracker.CarriedThing); if (job != null) { curJob.targetA = job.targetA; curJob.targetB = job.targetB; curJob.targetC = job.targetC; curJob.count = job.count; curJob.haulOpportunisticDuplicates = job.haulOpportunisticDuplicates; curJob.haulMode = job.haulMode; actor.jobs.curDriver.JumpToToil(nextToilOnPlaceFailOrIncomplete); } else { Log.Error(string.Concat("Incomplete haul for ", actor, ": Could not find anywhere to put ", actor.carryTracker.CarriedThing, " near ", actor.Position, ". Destroying. This should never happen!")); actor.carryTracker.CarriedThing.Destroy(); } } }
public Job TryOpportunisticJob(Job job) { if ((int)pawn.def.race.intelligence < 2) { return(null); } if (pawn.Faction != Faction.OfPlayer) { return(null); } if (pawn.Drafted) { return(null); } if (job.playerForced) { return(null); } if ((int)pawn.RaceProps.intelligence < 2) { return(null); } if (!job.def.allowOpportunisticPrefix) { return(null); } if (pawn.WorkTagIsDisabled(WorkTags.ManualDumb | WorkTags.Hauling)) { return(null); } if (pawn.InMentalState || pawn.IsBurning()) { return(null); } IntVec3 cell = job.targetA.Cell; if (!cell.IsValid || cell.IsForbidden(pawn)) { return(null); } float num = pawn.Position.DistanceTo(cell); if (num < 3f) { return(null); } List <Thing> list = pawn.Map.listerHaulables.ThingsPotentiallyNeedingHauling(); for (int i = 0; i < list.Count; i++) { Thing thing = list[i]; float num2 = pawn.Position.DistanceTo(thing.Position); if (num2 > 30f || num2 > num * 0.5f || num2 + thing.Position.DistanceTo(cell) > num * 1.7f || pawn.Map.reservationManager.FirstRespectedReserver(thing, pawn) != null || thing.IsForbidden(pawn) || !HaulAIUtility.PawnCanAutomaticallyHaulFast(pawn, thing, forced: false)) { continue; } StoragePriority currentPriority = StoreUtility.CurrentStoragePriorityOf(thing); IntVec3 foundCell = IntVec3.Invalid; if (!StoreUtility.TryFindBestBetterStoreCellFor(thing, pawn, pawn.Map, currentPriority, pawn.Faction, out foundCell)) { continue; } float num3 = foundCell.DistanceTo(cell); if (!(num3 > 50f) && !(num3 > num * 0.6f) && !(num2 + thing.Position.DistanceTo(foundCell) + num3 > num * 1.7f) && !(num2 + num3 > num) && pawn.Position.WithinRegions(thing.Position, pawn.Map, 25, TraverseParms.For(pawn)) && foundCell.WithinRegions(cell, pawn.Map, 25, TraverseParms.For(pawn))) { if (DebugViewSettings.drawOpportunisticJobs) { Log.Message("Opportunistic job spawned"); pawn.Map.debugDrawer.FlashLine(pawn.Position, thing.Position, 600, SimpleColor.Red); pawn.Map.debugDrawer.FlashLine(thing.Position, foundCell, 600, SimpleColor.Green); pawn.Map.debugDrawer.FlashLine(foundCell, cell, 600, SimpleColor.Blue); } return(HaulAIUtility.HaulToCellStorageJob(pawn, thing, foundCell, fitInStoreCell: false)); } } return(null); }
public static Toil PlaceHauledThingInCell(TargetIndex cellInd, Toil nextToilOnPlaceFailOrIncomplete, bool storageMode) { Toil toil = new Toil(); 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 + " tried to place hauled thing in cell but is not hauling anything."); } else { SlotGroup slotGroup = actor.Map.slotGroupManager.SlotGroupAt(cell); if (slotGroup != null && slotGroup.Settings.AllowedToAccept(actor.carryTracker.CarriedThing)) { actor.Map.designationManager.RemoveAllDesignationsOn(actor.carryTracker.CarriedThing, false); } Action <Thing, int> placedAction = null; if (curJob.def == JobDefOf.DoBill) { placedAction = delegate(Thing th, int added) { if (curJob.placedThings == null) { curJob.placedThings = new List <ThingStackPartClass>(); } ThingStackPartClass thingStackPartClass = curJob.placedThings.Find((ThingStackPartClass x) => x.thing == th); if (thingStackPartClass != null) { thingStackPartClass.Count += added; } else { curJob.placedThings.Add(new ThingStackPartClass(th, added)); } }; } Thing thing = default(Thing); if (!actor.carryTracker.TryDropCarriedThing(cell, ThingPlaceMode.Direct, out thing, placedAction)) { if (storageMode) { IntVec3 c = default(IntVec3); if (nextToilOnPlaceFailOrIncomplete != null && StoreUtility.TryFindBestBetterStoreCellFor(actor.carryTracker.CarriedThing, actor, actor.Map, StoragePriority.Unstored, actor.Faction, out c, true)) { if (actor.CanReserve(c, 1, -1, null, false)) { actor.Reserve(c, actor.CurJob, 1, -1, null); } actor.CurJob.SetTarget(cellInd, c); actor.jobs.curDriver.JumpToToil(nextToilOnPlaceFailOrIncomplete); } else { Job job = HaulAIUtility.HaulAsideJobFor(actor, actor.carryTracker.CarriedThing); if (job != null) { curJob.targetA = job.targetA; curJob.targetB = job.targetB; curJob.targetC = job.targetC; curJob.count = job.count; curJob.haulOpportunisticDuplicates = job.haulOpportunisticDuplicates; curJob.haulMode = job.haulMode; actor.jobs.curDriver.JumpToToil(nextToilOnPlaceFailOrIncomplete); } else { Log.Error("Incomplete haul for " + actor + ": Could not find anywhere to put " + actor.carryTracker.CarriedThing + " near " + actor.Position + ". Destroying. This should never happen!"); actor.carryTracker.CarriedThing.Destroy(DestroyMode.Vanish); } } } else if (nextToilOnPlaceFailOrIncomplete != null) { actor.jobs.curDriver.JumpToToil(nextToilOnPlaceFailOrIncomplete); } } } }; return(toil); }