static Job TryHaulStage(Pawn pawn, IntVec3 jobCell, ProximityCheck proximityCheck) { foreach (var thing in pawn.Map.listerHaulables.ThingsPotentiallyNeedingHauling()) { if (thingProximityStage.TryGetValue(thing, out var proximityStage) && proximityStage == ProximityStage.Fail) { continue; } var newProximityStage = CanHaul(proximityStage, pawn, thing, jobCell, proximityCheck, out var storeCell); // Debug.WriteLine($"{pawn} for {thing} proximity stage: {proximityStage} -> {newProximityStage}"); thingProximityStage.SetOrAdd(thing, newProximityStage); if (newProximityStage != ProximityStage.Success) { continue; } #if RELEASE if (DebugViewSettings.drawOpportunisticJobs) { #endif pawn.Map.debugDrawer.FlashLine(pawn.Position, jobCell, 600, SimpleColor.Red); pawn.Map.debugDrawer.FlashLine(pawn.Position, thing.Position, 600, SimpleColor.Green); pawn.Map.debugDrawer.FlashLine(thing.Position, storeCell, 600, SimpleColor.Green); pawn.Map.debugDrawer.FlashLine(storeCell, jobCell, 600, SimpleColor.Green); #if RELEASE } #endif var haulTracker = HaulTracker.CreateAndAdd(SpecialHaulType.Opportunity, pawn, jobCell); return(PuahJob(haulTracker, pawn, thing, storeCell) ?? HaulAIUtility.HaulToCellStorageJob(pawn, thing, storeCell, false)); } return(null); }
static Job TryHaulStage(Pawn pawn, IntVec3 jobCell, ProximityCheck proximityCheck) { foreach (var thing in pawn.Map.listerHaulables.ThingsPotentiallyNeedingHauling()) { if (thingProximityStage.TryGetValue(thing, out var proximityStage) && proximityStage == ProximityStage.Fail) { continue; } var newProximityStage = CanHaul(proximityStage, pawn, thing, jobCell, proximityCheck, out var storeCell); Debug.WriteLine($"{pawn} for {thing} proximity stage: {proximityStage} -> {newProximityStage}"); thingProximityStage.SetOrAdd(thing, newProximityStage); if (newProximityStage != ProximityStage.Success) { continue; } 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, storeCell, 600, SimpleColor.Green); pawn.Map.debugDrawer.FlashLine(storeCell, jobCell, 600, SimpleColor.Blue); } pawnHaulToCell.SetOrAdd(pawn, true); return(PuahJob(pawn, jobCell, 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); } } // we need storeCell everywhere, so cache it if (!cachedStoreCell.TryGetValue(thing, out storeCell)) { var currentPriority = StoreUtility.CurrentStoragePriorityOf(thing); if (!StoreUtility.TryFindBestBetterStoreCellFor(thing, pawn, pawn.Map, currentPriority, pawn.Faction, out storeCell)) { return(ProximityStage.Fail); } } cachedStoreCell.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); }
private void Start() { proximityCheck = GameObject.FindObjectOfType <ProximityCheck>(); }