static bool UsePuahFirstUnloadableThing(ref ThingCount __result, Pawn pawn) { if (!haulToInventory.Value || !enabled.Value) { return(true); } __result = JooStoreUtility.PuahFirstUnloadableThing(pawn); return(false); }
static bool UsePuahAllocateThingAtCell_GetStore(ref bool __result, Thing thing, Pawn carrier, Map map, StoragePriority currentPriority, Faction faction, ref IntVec3 foundCell) { if (!haulToInventory.Value || !enabled.Value) { return(true); } __result = JooStoreUtility.PuahAllocateThingAtCell_GetStore(thing, carrier, map, currentPriority, faction, out foundCell); return(false); }
static Job HaulBeforeSupply(Pawn pawn, Thing constructible, Thing th) { if (!haulBeforeSupply.Value || !enabled.Value) { return(null); } if (JooStoreUtility.PuahHasThingsHauled(pawn)) { Debug.WriteLine($"{RealTime.frameCount} {pawn} Aborting {MethodBase.GetCurrentMethod().Name}() already holding items."); return(null); } return(Helper.CatchStanding(pawn, Hauling.HaulBeforeCarry(pawn, constructible.Position, th))); }
static bool UseTryFindBestBetterStoreCellFor_ClosestToDestCell(Thing t, Pawn carrier, Map map, StoragePriority currentPriority, Faction faction, out IntVec3 foundCell, bool needAccurateResult) { if (!haulToInventory.Value || !enabled.Value) { return(StoreUtility.TryFindBestBetterStoreCellFor(t, carrier, map, currentPriority, faction, out foundCell, needAccurateResult)); } var haulTracker = haulTrackers.GetValueSafe(carrier); return(JooStoreUtility.TryFindBestBetterStoreCellFor_ClosestToDestCell( t, haulTracker?.destCell ?? IntVec3.Invalid, carrier, map, currentPriority, faction, out foundCell, haulTracker?.destCell.IsValid ?? false)); }
static Job TryOpportunisticJob(Pawn_JobTracker jobTracker, Job job) { // Debug.WriteLine($"Opportunity checking {job}"); var pawn = Traverse.Create(jobTracker).Field("pawn").GetValue <Pawn>(); if (JooStoreUtility.PuahHasThingsHauled(pawn)) { Debug.WriteLine($"{RealTime.frameCount} {pawn} Aborting {MethodBase.GetCurrentMethod().Name}() during {job}; already holding items."); return(null); } var jobCell = job.targetA.Cell; if (job.def == JobDefOf.DoBill && haulBeforeBill.Value && enabled.Value) { // Debug.WriteLine($"Bill: '{job.bill}' label: '{job.bill.Label}'"); // Debug.WriteLine($"Recipe: '{job.bill.recipe}' workerClass: '{job.bill.recipe.workerClass}'"); foreach (var localTargetInfo in job.targetQueueB) { if (localTargetInfo.Thing == null) { continue; } if (HaulAIUtility.PawnCanAutomaticallyHaulFast(pawn, localTargetInfo.Thing, false)) { // permitted when bleeding because facilitates whatever bill is important enough to do while bleeding // may save precious time going back for ingredients... unless we want only 1 medicine ASAP; it's a trade-off var storeJob = Hauling.HaulBeforeCarry(pawn, jobCell, localTargetInfo.Thing); if (storeJob != null) { return(Helper.CatchStanding(pawn, storeJob)); } } } } if (skipIfBleeding.Value && pawn.health.hediffSet.BleedRateTotal > 0.001f) { return(null); } // return Helper.CatchStanding(pawn, Hauling.TryHaul(pawn, jobCell) ?? Cleaning.TryClean(pawn, jobCell)); return(Helper.CatchStanding(pawn, Hauling.TryHaul(pawn, jobCell))); }
// "Optimize hauling" public static Job HaulBeforeCarry(Pawn pawn, IntVec3 destCell, Thing thing) { if (thing.ParentHolder is Pawn_InventoryTracker) { return(null); } if (!JooStoreUtility.TryFindBestBetterStoreCellFor_ClosestToDestCell( thing, destCell, pawn, pawn.Map, StoreUtility.CurrentStoragePriorityOf(thing), pawn.Faction, out var storeCell, true)) { return(null); } var supplyFromHereDist = thing.Position.DistanceTo(destCell); var supplyFromStoreDist = storeCell.DistanceTo(destCell); // Debug.WriteLine($"Carry from here: {supplyFromHereDist}; carry from store: {supplyFromStoreDist}"); // [KV] Infinite Storage https://steamcommunity.com/sharedfiles/filedetails/?id=1233893175 // infinite storage has an interaction spot 1 tile away from itself if (supplyFromStoreDist + 1 < supplyFromHereDist) { // Debug.WriteLine( // $"'{pawn}' prefixed job with haul for '{thing.Label}' because '{storeCell.GetSlotGroup(pawn.Map)}' is closer to original destination '{destCell}'."); #if RELEASE if (DebugViewSettings.drawOpportunisticJobs) { #endif pawn.Map.debugDrawer.FlashLine(pawn.Position, thing.Position, 600, SimpleColor.White); // unchanged pawn.Map.debugDrawer.FlashLine(thing.Position, destCell, 600, SimpleColor.Magenta); pawn.Map.debugDrawer.FlashLine(thing.Position, storeCell, 600, SimpleColor.Cyan); pawn.Map.debugDrawer.FlashLine(storeCell, destCell, 600, SimpleColor.Cyan); #if RELEASE } #endif var haulTracker = HaulTracker.CreateAndAdd(SpecialHaulType.HaulBeforeCarry, pawn, destCell); return(PuahJob(haulTracker, pawn, thing, storeCell) ?? HaulAIUtility.HaulToCellStorageJob(pawn, thing, storeCell, false)); } return(null); }
static ProximityStage CanHaul(ProximityStage proximityStage, Pawn pawn, Thing thing, IntVec3 jobCell, ProximityCheck proximityCheck, out IntVec3 storeCell) { storeCell = IntVec3.Invalid; var pawnToJob = pawn.Position.DistanceTo(jobCell); var pawnToThing = pawn.Position.DistanceTo(thing.Position); if (proximityStage < ProximityStage.StoreToJob) { var atMax = maxStartToThing.Value > 0 && pawnToThing > maxStartToThing.Value; var atMaxPct = maxStartToThingPctOrigTrip.Value > 0 && pawnToThing > pawnToJob * maxStartToThingPctOrigTrip.Value; var pawnToThingFail = atMax || atMaxPct; switch (proximityCheck) { case ProximityCheck.Both when pawnToThingFail: return(ProximityStage.PawnToThing); } var thingToJob = thing.Position.DistanceTo(jobCell); // if this one exceeds the maximum the next maxTotalTripPctOrigTrip check certainly will if (maxTotalTripPctOrigTrip.Value > 0 && pawnToThing + thingToJob > pawnToJob * maxTotalTripPctOrigTrip.Value) { return(ProximityStage.Fail); } if (pawn.Map.reservationManager.FirstRespectedReserver(thing, pawn) != null) { return(ProximityStage.Fail); } if (thing.IsForbidden(pawn)) { return(ProximityStage.Fail); } if (!HaulAIUtility.PawnCanAutomaticallyHaulFast(pawn, thing, false)) { return(ProximityStage.Fail); } } var currentPriority = StoreUtility.CurrentStoragePriorityOf(thing); if (!JooStoreUtility.TryFindBestBetterStoreCellFor_ClosestToDestCell(thing, IntVec3.Invalid, pawn, pawn.Map, currentPriority, pawn.Faction, out storeCell, true)) { return(ProximityStage.Fail); } // we need storeCell everywhere, so cache it cachedOpportunityStoreCell.SetOrAdd(thing, storeCell); var storeToJob = storeCell.DistanceTo(jobCell); if (proximityStage < ProximityStage.PawnToThingRegion) { var atMax2 = maxStoreToJob.Value > 0 && storeToJob > maxStoreToJob.Value; var atMaxPct2 = maxStoreToJobPctOrigTrip.Value > 0 && storeToJob > pawnToJob * maxStoreToJobPctOrigTrip.Value; var storeToJobFail = atMax2 || atMaxPct2; switch (proximityCheck) { case ProximityCheck.Both when storeToJobFail: return(ProximityStage.StoreToJob); case ProximityCheck.Either when proximityStage == ProximityStage.PawnToThing && storeToJobFail: return(ProximityStage.StoreToJob); } var thingToStore = thing.Position.DistanceTo(storeCell); if (maxTotalTripPctOrigTrip.Value > 0 && pawnToThing + thingToStore + storeToJob > pawnToJob * maxTotalTripPctOrigTrip.Value) { return(ProximityStage.Fail); } if (maxNewLegsPctOrigTrip.Value > 0 && pawnToThing + storeToJob > pawnToJob * maxNewLegsPctOrigTrip.Value) { return(ProximityStage.Fail); } } bool PawnToThingRegionFail() { return(maxStartToThingRegionLookCount.Value > 0 && !pawn.Position.WithinRegions( thing.Position, pawn.Map, maxStartToThingRegionLookCount.Value, TraverseParms.For(pawn))); } bool StoreToJobRegionFail(IntVec3 _storeCell) { return(maxStoreToJobRegionLookCount.Value > 0 && !_storeCell.WithinRegions(jobCell, pawn.Map, maxStoreToJobRegionLookCount.Value, TraverseParms.For(pawn))); } switch (proximityCheck) { case ProximityCheck.Both when PawnToThingRegionFail(): return(ProximityStage.PawnToThingRegion); case ProximityCheck.Both when StoreToJobRegionFail(storeCell): return(ProximityStage.Fail); case ProximityCheck.Either when proximityStage == ProximityStage.PawnToThingRegion && StoreToJobRegionFail(storeCell): return(ProximityStage.Fail); } return(ProximityStage.Success); }