Example #1
0
            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>();
 }