private int CheckForHunger; // Random 180 to 600

        #endregion Fields

        #region Methods

        public static Thing FindMeat(Pawn pawn, TraverseParms traverseParams)
        {
            ThingRequest meatRequest = ThingRequest.ForGroup(ThingRequestGroup.FoodNotPlant);
            Predicate<Thing> availMeatPredicate = food =>
            {
                return (isMeaty(pawn, food) && (Find.Reservations.CanReserve(pawn, food, 1) == true));
            };

            Thing thing = GenClosest.ClosestThingReachable(pawn.Position, meatRequest, PathEndMode.Touch, traverseParams, 100f, availMeatPredicate);
            return thing;
        }
        public static Corpse FindMeatyCorpse(Pawn pawn, TraverseParms traverseParams)
        {
            ThingRequest corpseRequest = ThingRequest.ForGroup(ThingRequestGroup.Corpse);
            Predicate<Thing> availCorpsePredicate = corpse =>
            {
                return (isMeaty(pawn, corpse) && (Find.Reservations.CanReserve(pawn, corpse, 1) == true));
            };

            Corpse closestCorpse = GenClosest.ClosestThingReachable(pawn.Position, corpseRequest, PathEndMode.Touch, traverseParams, 100f, availCorpsePredicate) as Corpse;
            return closestCorpse;
        }
        public static Pawn FindThreat(Pawn pawn, TraverseParms traverseParams)
        {
            ThingRequest agressorRequest = ThingRequest.ForGroup(ThingRequestGroup.Pawn);
            Predicate<Thing> availAgressorPredicate = p =>
            {
                Pawn agressor = p as Pawn;
                return isPossibleThreat(agressor, pawn);
            };

            Pawn closestThreat = GenClosest.ClosestThingReachable(pawn.Position, agressorRequest, PathEndMode.Touch, traverseParams, 100f, availAgressorPredicate) as Pawn;
            return closestThreat;
        }
        public static Pawn FindBloodyPrey(Pawn pawn, TraverseParms traverseParams)
        {
            ThingRequest preyRequest = ThingRequest.ForGroup(ThingRequestGroup.Pawn);
            Predicate<Thing> availPreyPredicate = p =>
            {
                Pawn prey = p as Pawn;

                return isPossibleBloodyPrey(prey, pawn);
            };

            Pawn closestBloodyPrey = GenClosest.ClosestThingReachable(pawn.Position, preyRequest, PathEndMode.Touch, traverseParams, 100f, availPreyPredicate) as Pawn;
            return closestBloodyPrey;
        }
示例#5
0
        public IntVec3? NearestTerrainOfType(IntVec3 root, Func<TerrainDef, bool> terrainPred,
            TraverseParms traverseParams, int minRegions=9, int maxRegions=0, float maxDistance=9999f)
        {
            IntVec3? nearest = null;

            Region validRegionAt = Find.RegionGrid.GetValidRegionAt(root);
            if (validRegionAt == null)
            {
                return nearest;
            }

            maxRegions = (maxRegions == 0 ? 50 : maxRegions);

            float maxDistSquared = maxDistance * maxDistance;
            float closestDistSquared = 99999f;
            int regionsSeen = 0;
            RegionEntryPredicate entryCondition = r =>
                r.Allows(traverseParams, false) &&
                (maxDistance > 5000f || r.extentsClose.ClosestDistSquaredTo(root) < maxDistSquared);

            RegionProcessor regionProc = delegate(Region r)
            {
                if (!r.Allows(traverseParams, true)) { return false; }
                // If a region definitely doesn't have the correct terrain, skip it.
                if (!RegionMayContain(r, terrainPred)) { return false; }

                var tg = Find.TerrainGrid;
                foreach (var cellVec in r.Cells)
                {
                    float cellDistSquared = (cellVec - root).LengthHorizontalSquared;
                    var cellTerrain = tg.TerrainAt(cellVec);
                    if ((cellDistSquared < closestDistSquared && cellDistSquared < maxDistSquared)
                        && (terrainPred == null || terrainPred(cellTerrain)))
                    {
                        nearest = cellVec;
                        closestDistSquared = cellDistSquared;
                    }
                }

                regionsSeen++;
                return regionsSeen > minRegions && nearest != null;
            };

            RegionTraverser.BreadthFirstTraverse(validRegionAt, entryCondition, regionProc, maxRegions);
            return nearest;
        }
        public static Thing ClosestThing_Global_Reachable(IntVec3 center, IEnumerable<Thing> searchSet, PathEndMode pathMode, TraverseParms traverseParams, float maxDistance, Pawn pawn)
        {
            if (searchSet == null)
            {
                return null;
            }
            int num = 0;
            int num2 = 0;
            Thing result = null;
            int num3 = -2147483648;
            int num4 = 0;
            float num5 = maxDistance * maxDistance;
            float num6 = 2.14748365E+09f;
            foreach (Thing current in searchSet)
            {
                num2++;
                float lengthHorizontalSquared = (center - current.Position).LengthHorizontalSquared;
                if (lengthHorizontalSquared <= num5)
                {
                    if (num4 > num3 || lengthHorizontalSquared < num6)
                    {
                        if (center.CanReach(current, pathMode, traverseParams))
                        {
                            if (current.SpawnedInWorld)
                            {

                                if(((Building_DroidChargePad)current).IsAvailable(pawn))
                                {
                                    result = current;
                                    num6 = lengthHorizontalSquared;
                                    num3 = num4;
                                    num++;
                                }
                            }
                        }
                    }
                }
            }
            return result;
        }
示例#7
0
        // Token: 0x06000063 RID: 99 RVA: 0x00004318 File Offset: 0x00002518
        protected override IEnumerable <Toil> MakeNewToils()
        {
            this.FailOnDespawnedOrNull(TargetIndex.A);
            var toilInv       = new Toil();
            var toilEquipGoto = new Toil();
            var toilEquip     = new Toil();
            var toilGoto      = new Toil();
            var toilCast      = new Toil();
            var toilTouch     = new Toil();
            var toilBeat      = new Toil();
            var toilBash      = new Toil();
            var HasPrimFE     = false;
            var HasPrimFB     = false;

            if (pawn.equipment.Primary != null)
            {
                if (pawn.equipment.Primary.def.defName == FEDefName && FWFoamUtility.HasFEFoam(pawn.equipment.Primary))
                {
                    HasPrimFE = true;
                }
                else if (pawn.equipment.Primary.def.defName == FBDefName)
                {
                    HasPrimFB = true;
                }
            }

            if (!HasPrimFE)
            {
                var fb = HasPrimFB;
                toilInv.initAction = delegate
                {
                    var            Swap            = false;
                    ThingWithComps invGearToEquip2 = null;
                    ThingWithComps primToSwap2     = null;
                    Thing          RemoveThing     = null;
                    Thing          BackupThing2    = null;
                    if (pawn.equipment.Primary != null)
                    {
                        primToSwap2 = pawn.equipment.Primary;
                    }

                    foreach (var invThing2 in pawn.inventory.innerContainer)
                    {
                        if (invThing2.def.defName != FEDefName || !FWFoamUtility.HasFEFoam(invThing2))
                        {
                            if (invThing2.def.defName == FBDefName)
                            {
                                BackupThing2 = invThing2;
                            }
                        }
                        else
                        {
                            RemoveThing     = invThing2;
                            invGearToEquip2 = (ThingWithComps)invThing2;
                            if (primToSwap2 != null)
                            {
                                Swap = true;
                            }

                            break;
                        }
                    }

                    if (invGearToEquip2 == null && !fb && BackupThing2 != null)
                    {
                        RemoveThing     = BackupThing2;
                        invGearToEquip2 = (ThingWithComps)BackupThing2;
                        if (primToSwap2 != null)
                        {
                            Swap = true;
                        }
                    }

                    if (invGearToEquip2 == null)
                    {
                        return;
                    }

                    var primDef = "";
                    if (Swap)
                    {
                        primDef = pawn.equipment.Primary.def.defName;
                        pawn.equipment.Remove(pawn.equipment.Primary);
                    }

                    pawn.inventory.innerContainer.Remove(RemoveThing);
                    pawn.equipment.MakeRoomFor(invGearToEquip2);
                    pawn.equipment.AddEquipment(invGearToEquip2);
                    if (Swap)
                    {
                        pawn.inventory.innerContainer.TryAdd(primToSwap2);
                    }

                    if (!Swap)
                    {
                        return;
                    }

                    var returnType = "SI";
                    if (pawn.equipment.Primary.def.defName != FEDefName &&
                        pawn.equipment.Primary.def.defName != FBDefName)
                    {
                        return;
                    }

                    var primary = pawn.equipment.Primary;
                    ((FireWardenData)primary).FWSwapType = returnType;
                    ((FireWardenData)primary).FWPawnID   = pawn.thingIDNumber;
                    ((FireWardenData)primary).FWPrimDef  = primDef;
                    if (!DebugFWData)
                    {
                        return;
                    }

                    var Test      = pawn.equipment.Primary;
                    var debugTest = pawn.Label + " : ";
                    debugTest = debugTest + Test.Label + " : ";
                    debugTest = debugTest + pawn.equipment.Primary.GetType() + " : ";
                    if (((FireWardenData)Test).FWSwapType != null)
                    {
                        debugTest = debugTest + ((FireWardenData)Test).FWSwapType + " : ";
                    }
                    else
                    {
                        debugTest += "null : ";
                    }

                    debugTest = debugTest + ((FireWardenData)Test).FWPawnID + " : ";
                    if (((FireWardenData)Test).FWPrimDef != null)
                    {
                        debugTest += ((FireWardenData)Test).FWPrimDef;
                    }
                    else
                    {
                        debugTest += "null";
                    }

                    Messages.Message(debugTest, pawn, MessageTypeDefOf.NeutralEvent, false);
                };
                toilInv.defaultCompleteMode = ToilCompleteMode.FinishedBusy;
                yield return(toilInv);
            }

            var FWEquipping   = Controller.Settings.EquippingDone;
            var FWSearchRange = (float)Controller.Settings.SearchRange;

            if (FWSearchRange < 25f)
            {
                FWSearchRange = 25f;
            }

            if (FWSearchRange > 75f)
            {
                FWSearchRange = 75f;
            }

            HasPrimFE = false;
            HasPrimFB = false;
            if (pawn.equipment.Primary != null)
            {
                if (pawn.equipment.Primary.def.defName == FEDefName && FWFoamUtility.HasFEFoam(pawn.equipment.Primary))
                {
                    HasPrimFE = true;
                }
                else if (pawn.equipment.Primary.def.defName == FBDefName)
                {
                    HasPrimFB = true;
                }
            }

            if (!HasPrimFE && !HasPrimFB && FWEquipping)
            {
                ThingWithComps invGearToEquip = null;
                ThingWithComps primToSwap     = null;
                Thing          BackupThing    = null;
                if (pawn.equipment.Primary != null)
                {
                    primToSwap = pawn.equipment.Primary;
                }

                foreach (var invThing in pawn.inventory.innerContainer)
                {
                    if (invThing.def.defName == FEDefName && FWFoamUtility.HasFEFoam(invThing))
                    {
                        invGearToEquip = (ThingWithComps)invThing;
                        if (primToSwap != null)
                        {
                        }

                        break;
                    }

                    if (invThing.def.defName == FBDefName)
                    {
                        BackupThing = invThing;
                    }
                }

                if (invGearToEquip == null && BackupThing != null)
                {
                    invGearToEquip = (ThingWithComps)BackupThing;
                }

                if (invGearToEquip == null)
                {
                    Thing ThingToGrab    = null;
                    var   skip           = Controller.Settings.BrawlerNotOK && pawn.story.traits.HasTrait(TraitDefOf.Brawler);
                    var   traverseParams = TraverseParms.For(pawn);

                    bool validatorFE(Thing t)
                    {
                        return(!t.IsForbidden(pawn) && pawn.CanReserve(t) && FWFoamUtility.HasFEFoam(t) &&
                               !FWFoamUtility.ReplaceFEFoam(t));
                    }

                    bool validatorFB(Thing t)
                    {
                        return(!t.IsForbidden(pawn) && pawn.CanReserve(t));
                    }

                    if (!skip)
                    {
                        var FElist = pawn.Map.listerThings.ThingsOfDef(DefDatabase <ThingDef> .GetNamed(FEDefName));
                        var FEGrab = GenClosest.ClosestThing_Global_Reachable(pawn.Position, pawn.Map, FElist,
                                                                              PathEndMode.OnCell, traverseParams, FWSearchRange, validatorFE);
                        if (FEGrab != null)
                        {
                            ThingToGrab = FEGrab;
                        }
                        else
                        {
                            var FBlist = pawn.Map.listerThings.ThingsOfDef(DefDatabase <ThingDef> .GetNamed(FBDefName));
                            var FBGrab = GenClosest.ClosestThing_Global_Reachable(pawn.Position, pawn.Map, FBlist,
                                                                                  PathEndMode.OnCell, traverseParams, FWSearchRange, validatorFB);
                            if (FBGrab != null)
                            {
                                ThingToGrab = FBGrab;
                            }
                        }
                    }
                    else
                    {
                        var FBlist2 = pawn.Map.listerThings.ThingsOfDef(DefDatabase <ThingDef> .GetNamed(FBDefName));
                        var FBGrab2 = GenClosest.ClosestThing_Global_Reachable(pawn.Position, pawn.Map, FBlist2,
                                                                               PathEndMode.OnCell, traverseParams, FWSearchRange, validatorFB);
                        if (FBGrab2 != null)
                        {
                            ThingToGrab = FBGrab2;
                        }
                    }

                    if (ThingToGrab != null)
                    {
                        toilEquipGoto.initAction = delegate
                        {
                            if (Map.reservationManager.CanReserve(pawn, ThingToGrab))
                            {
                                pawn.Reserve(ThingToGrab, job);
                            }

                            pawn.pather.StartPath(ThingToGrab, PathEndMode.OnCell);
                        };
                        toilEquipGoto.FailOn(ThingToGrab.DestroyedOrNull);
                        toilEquipGoto.AddFailCondition(() => FWHasFE(pawn) && ThingToGrab.def.defName == FEDefName);
                        toilEquipGoto.AddFailCondition(() => FWHasFB(pawn) && ThingToGrab.def.defName == FBDefName);
                        toilEquipGoto.defaultCompleteMode = ToilCompleteMode.PatherArrival;
                        yield return(toilEquipGoto);

                        toilEquip.initAction = delegate
                        {
                            var primDeEquip = pawn.equipment.Primary;
                            var primDef     = "N";
                            if (primDeEquip != null)
                            {
                                primDef = pawn.equipment.Primary.def.defName;
                                pawn.equipment.Remove(pawn.equipment.Primary);
                                pawn.inventory.innerContainer.TryAdd(primDeEquip);
                            }

                            var            FWGrabWithComps = (ThingWithComps)ThingToGrab;
                            ThingWithComps FWGrabbed;
                            if (FWGrabWithComps.def.stackLimit > 1 && FWGrabWithComps.stackCount > 1)
                            {
                                FWGrabbed = (ThingWithComps)FWGrabWithComps.SplitOff(1);
                            }
                            else
                            {
                                FWGrabbed = FWGrabWithComps;
                                FWGrabbed.DeSpawn();
                            }

                            pawn.equipment.MakeRoomFor(FWGrabbed);
                            pawn.equipment.AddEquipment(FWGrabbed);
                            var returnType = "EN";
                            if (pawn.equipment.Primary.def.defName != FEDefName &&
                                pawn.equipment.Primary.def.defName != FBDefName)
                            {
                                return;
                            }

                            var primary = pawn.equipment.Primary;
                            ((FireWardenData)primary).FWSwapType = returnType;
                            ((FireWardenData)primary).FWPawnID   = pawn.thingIDNumber;
                            ((FireWardenData)primary).FWPrimDef  = primDef;
                            if (!DebugFWData)
                            {
                                return;
                            }

                            var Test      = pawn.equipment.Primary;
                            var debugTest = pawn.Label + " : ";
                            debugTest = debugTest + Test.Label + " : ";
                            debugTest = debugTest + pawn.equipment.Primary.GetType() + " : ";
                            if ((Test as FireWardenData)?.FWSwapType != null)
                            {
                                debugTest = debugTest + ((FireWardenData)Test).FWSwapType + " : ";
                            }
                            else
                            {
                                debugTest += "null : ";
                            }

                            debugTest = debugTest + ((FireWardenData)Test).FWPawnID + " : ";
                            if (((FireWardenData)Test).FWPrimDef != null)
                            {
                                debugTest += ((FireWardenData)Test).FWPrimDef;
                            }
                            else
                            {
                                debugTest += "null";
                            }

                            Messages.Message(debugTest, pawn, MessageTypeDefOf.NeutralEvent, false);
                        };
                        toilEquip.AddFailCondition(() => FWHasFE(pawn) && ThingToGrab.def.defName == FEDefName);
                        toilEquip.AddFailCondition(() => FWHasFB(pawn) && ThingToGrab.def.defName == FBDefName);
                        toilEquip.defaultCompleteMode = ToilCompleteMode.FinishedBusy;
                        yield return(toilEquip);
                    }
                }
            }

            var HasPrimFEEq = pawn.equipment.Primary != null && pawn.equipment.Primary.def.defName == FEDefName &&
                              FWFoamUtility.HasFEFoam(pawn.equipment.Primary);

            if (HasPrimFEEq)
            {
                var FEVerbToUse  = pawn.TryGetAttackVerb(TargetFire);
                var RangeFireExt = 10f;
                if (FEVerbToUse != null)
                {
                    pawn.jobs.curJob.verbToUse = FEVerbToUse;
                    RangeFireExt  = pawn.jobs.curJob.verbToUse.verbProps.range;
                    RangeFireExt *= (float)(Controller.Settings.HowClose / 100.0);
                    if (RangeFireExt < 3f)
                    {
                        RangeFireExt = 3f;
                    }

                    if (RangeFireExt > pawn.jobs.curJob.verbToUse.verbProps.range)
                    {
                        RangeFireExt = pawn.jobs.curJob.verbToUse.verbProps.range;
                    }
                }

                toilGoto.initAction = delegate
                {
                    if (Map.reservationManager.CanReserve(pawn, TargetFire))
                    {
                        pawn.Reserve(TargetFire, job);
                    }

                    if (!CastPositionFinder.TryFindCastPosition(new CastPositionRequest
                    {
                        caster = pawn,
                        target = TargetFire,
                        verb = pawn.jobs.curJob.verbToUse,
                        maxRangeFromTarget = RangeFireExt,
                        wantCoverFromTarget = false
                    }, out var dest))
                    {
                        toilGoto.actor.jobs.EndCurrentJob(JobCondition.Incompletable);
                        return;
                    }

                    toilGoto.actor.pather.StartPath(dest, PathEndMode.OnCell);
                    pawn.Map.pawnDestinationReservationManager.Reserve(pawn, pawn.jobs.curJob, dest);
                };
                toilGoto.tickAction = delegate
                {
                    if (Controller.Settings.TooBrave)
                    {
                        return;
                    }

                    if (pawn.pather.Moving && pawn.pather.nextCell != TargetFire.Position)
                    {
                        StartTacklingFireIfAnyAt(pawn.pather.nextCell, toilCast);
                    }

                    if (pawn.Position != TargetFire.Position)
                    {
                        StartTacklingFireIfAnyAt(pawn.Position, toilCast);
                    }
                };
                toilGoto.FailOnDespawnedOrNull(TargetIndex.A);
                toilGoto.defaultCompleteMode = ToilCompleteMode.PatherArrival;
                toilGoto.atomicWithPrevious  = true;
                yield return(toilGoto);

                toilCast.initAction = delegate
                {
                    pawn.jobs.curJob.verbToUse.TryStartCastOn(TargetFire);
                    if (!TargetFire.Destroyed)
                    {
                        return;
                    }

                    pawn.records.Increment(RecordDefOf.FiresExtinguished);
                    pawn.jobs.EndCurrentJob(JobCondition.Succeeded);
                };
                toilCast.FailOnDespawnedOrNull(TargetIndex.A);
                toilCast.defaultCompleteMode = ToilCompleteMode.FinishedBusy;
                yield return(toilCast);
            }
            else
            {
                toilTouch.initAction = delegate
                {
                    if (Map.reservationManager.CanReserve(pawn, TargetFire))
                    {
                        pawn.Reserve(TargetFire, job);
                    }

                    pawn.pather.StartPath(TargetFire, PathEndMode.Touch);
                };
                toilTouch.tickAction = delegate
                {
                    if (Controller.Settings.TooBrave)
                    {
                        return;
                    }

                    if (pawn.pather.Moving && pawn.pather.nextCell != TargetFire.Position)
                    {
                        StartTacklingFireIfAnyAt(pawn.pather.nextCell, toilBeat);
                    }

                    if (pawn.Position != TargetFire.Position)
                    {
                        StartTacklingFireIfAnyAt(pawn.Position, toilBeat);
                    }
                };
                toilTouch.FailOnDespawnedOrNull(TargetIndex.A);
                toilTouch.defaultCompleteMode = ToilCompleteMode.PatherArrival;
                toilTouch.atomicWithPrevious  = true;
                yield return(toilTouch);

                toilBeat.tickAction = delegate
                {
                    if (!pawn.CanReachImmediate(TargetFire, PathEndMode.Touch))
                    {
                        JumpToToil(toilTouch);
                        return;
                    }

                    if (pawn.Position != TargetFire.Position && StartTacklingFireIfAnyAt(pawn.Position, toilBeat))
                    {
                        return;
                    }

                    if (pawn.equipment.Primary != null)
                    {
                        if (pawn.equipment.Primary.def.defName == FBDefName)
                        {
                            JumpToToil(toilBash);
                        }
                        else
                        {
                            pawn.natives.TryBeatFire(TargetFire);
                        }
                    }
                    else
                    {
                        pawn.natives.TryBeatFire(TargetFire);
                    }

                    if (!TargetFire.Destroyed)
                    {
                        return;
                    }

                    pawn.records.Increment(RecordDefOf.FiresExtinguished);
                    pawn.jobs.EndCurrentJob(JobCondition.Succeeded);
                };
                toilBeat.FailOnDespawnedOrNull(TargetIndex.A);
                toilBeat.defaultCompleteMode = ToilCompleteMode.Never;
                yield return(toilBeat);

                if (pawn.equipment.Primary == null || pawn.equipment.Primary.def.defName != FBDefName)
                {
                    yield break;
                }

                toilBash.initAction = delegate
                {
                    if (TargetFire != null && Map.reservationManager.CanReserve(pawn, TargetFire))
                    {
                        pawn.Reserve(TargetFire, job);
                    }

                    pawn.pather.StopDead();
                };
                toilBash.handlingFacing = true;
                toilBash.tickAction     = delegate
                {
                    pawn.rotationTracker.FaceTarget(pawn.CurJob.GetTarget(TargetIndex.A));
                    if (TargetFire != null)
                    {
                        pawn.Drawer.Notify_MeleeAttackOn(TargetFire);
                    }
                };
                toilBash.PlaySoundAtStart(SoundDefOf.Interact_BeatFire);
                toilBash.WithProgressBarToilDelay(TargetIndex.A);
                toilBash.AddFinishAction(delegate
                {
                    if (TargetFire != null && !TargetFire.Destroyed)
                    {
                        TargetFire.Destroy();
                    }
                });
                toilBash.FailOnDespawnedOrNull(TargetIndex.A);
                toilBash.defaultCompleteMode = ToilCompleteMode.Delay;
                var ticks     = 50;
                var WorkSpeed = pawn.GetStatValue(StatDefOf.WorkSpeedGlobal);
                if (WorkSpeed <= 0f)
                {
                    WorkSpeed = 1f;
                }

                ticks = (int)(ticks * (1f / WorkSpeed));
                if (ticks < 25)
                {
                    ticks = 25;
                }

                if (ticks > 200)
                {
                    ticks = 200;
                }

                toilBash.defaultDuration = ticks;
                yield return(toilBash);
            }
        }
        private static Pawn FindPawnTargetNearPlants(Pawn pawn)
        {
            Pawn victim = null;

            bool Predicate(Thing p) => p != null && p != pawn &&
            p.Faction != pawn.Faction &&
            ((Pawn)p).health.hediffSet.GetFirstHediffOfDef(PurpleIvyDefOf.PI_MaskingSprayHigh) == null;

            const float distance = 9999f;
            var         plants   = pawn.Map.listerThings.ThingsOfDef(PurpleIvyDefOf.PI_Nest);

            if (plants.Count == 0)
            {
                plants = pawn.Map.listerThings.ThingsOfDef(PurpleIvyDefOf.PurpleIvy);
            }
            if (plants.Count > 0)
            {
                victim = (Pawn)GenClosest.ClosestThingReachable(plants.RandomElement().Position,
                                                                pawn.Map, ThingRequest.ForGroup(ThingRequestGroup.Pawn), PathEndMode.Touch, TraverseParms.For(pawn, Danger.Deadly,
                                                                                                                                                              TraverseMode.PassDoors, false)
                                                                , distance, Predicate);
            }
            return(victim);
        }
        //The standard A* search algorithm has been modified to implement the bidirectional pathmax algorithm
        //("Inconsistent heuristics in theory and practice" Felner et al.) http://web.cs.du.edu/~sturtevant/papers/incnew.pdf
        internal PawnPath FindPathInner(IntVec3 start, LocalTargetInfo dest, TraverseParms traverseParms, PathEndMode peMode, HeuristicMode mode = HeuristicMode.Better)
        {
            //The initialization is largely unchanged from Core, aside from coding style in some spots
            #region initialization
            if (DebugSettings.pathThroughWalls)
            {
                traverseParms.mode = TraverseMode.PassAnything;
            }
            Pawn pawn            = traverseParms.pawn;
            bool canPassAnything = traverseParms.mode == TraverseMode.PassAnything;

            if (!ValidateFindPathParameters(pawn, start, dest, traverseParms, peMode, canPassAnything))
            {
                return(PawnPath.NotFound);
            }

            PfProfilerBeginSample(string.Concat("FindPath for ", pawn, " from ", start, " to ", dest, (!dest.HasThing) ? string.Empty : (" at " + dest.Cell)));
            destinationX = dest.Cell.x;
            destinationZ = dest.Cell.z;
            var cellIndices = this.map.cellIndices;
            curIndex         = cellIndices.CellToIndex(start);
            destinationIndex = cellIndices.CellToIndex(dest.Cell);
            if (!dest.HasThing || peMode == PathEndMode.OnCell)
            {
                destinationRect = CellRect.SingleCell(dest.Cell);
            }
            else
            {
                destinationRect = dest.Thing.OccupiedRect();
            }
            if (peMode == PathEndMode.Touch)
            {
                destinationRect = destinationRect.ExpandedBy(1);
            }
            destinationRect = destinationRect.ClipInsideMap(map);
            var regions = destinationRect.Cells.Select(c => this.map.regionGrid.GetValidRegionAt_NoRebuild(c)).Where(r => r != null);
            //Pretty sure this shouldn't be able to happen...
            if (mode == HeuristicMode.Better && !canPassAnything && !regions.Any())
            {
                mode = HeuristicMode.Vanilla;
                Log.Warning("Pathfinding destination not in region, must fall back to vanilla!");
            }
            destinationIsOneCell = (destinationRect.Width == 1 && destinationRect.Height == 1);
            this.pathGridDirect  = this.map.pathGrid.pathGrid;
            this.edificeGrid     = this.map.edificeGrid.InnerArray;
            statusOpenValue     += 2;
            statusClosedValue   += 2;
            if (statusClosedValue >= 65435)
            {
                ResetStatuses();
            }
            if (pawn?.RaceProps.Animal == true)
            {
                heuristicStrength = 30;
            }
            else
            {
                float lengthHorizontal = (start - dest.Cell).LengthHorizontal;
                heuristicStrength = (int)Math.Round(HeuristicStrengthHuman_DistanceCurve.Evaluate(lengthHorizontal));
            }
            closedCellCount = 0;
            openList.Clear();
            debug_pathFailMessaged   = false;
            debug_totalOpenListCount = 0;
            debug_openCellsPopped    = 0;

            PawnPathCostSettings pawnPathCosts = GetPawnPathCostSettings(traverseParms.pawn);

            moveTicksCardinal = pawnPathCosts.moveTicksCardinal;
            moveTicksDiagonal = pawnPathCosts.moveTicksDiagonal;

            //Where the magic happens
            RegionPathCostHeuristic regionCost = new RegionPathCostHeuristic(map, start, destinationRect, regions, traverseParms, pawnPathCosts);

            if (mode == HeuristicMode.Better)
            {
                if (canPassAnything)
                {
                    //Roughly preserves the Vanilla behavior of increasing path accuracy for shorter paths and slower pawns, though not as smoothly. Only applies to sappers.
                    heuristicStrength = Math.Max(1, (int)Math.Round(heuristicStrength / (float)moveTicksCardinal));
                }
                else
                {
                    var totalCostEst = (debug_totalHeuristicCostEstimate = regionCost.GetPathCostToRegion(curIndex)) + (moveTicksCardinal * 50);                     //Add constant cost so it tries harder on short paths
                    regionHeuristicWeightReal[1].x = totalCostEst / 2;
                    regionHeuristicWeightReal[2].x = totalCostEst;
                }
                regionHeuristicWeight = weightEnabled ? regionHeuristicWeightReal : regionHeuristicWeightNone;
            }
            else
            {
                regionHeuristicWeight = regionHeuristicWeightNone;
            }
            calcGrid[curIndex].knownCost     = 0;
            calcGrid[curIndex].heuristicCost = 0;
            calcGrid[curIndex].parentIndex   = curIndex;
            calcGrid[curIndex].status        = statusOpenValue;
            openList.Push(new CostNode(curIndex, 0));


            bool shouldCollideWithPawns = false;
            if (pawn != null)
            {
                shouldCollideWithPawns = PawnUtility.ShouldCollideWithPawns(pawn);
            }
            #endregion

            while (true)
            {
                PfProfilerBeginSample("Open cell pop");
                if (openList.Count <= 0)
                {
                    break;
                }
                debug_openCellsPopped++;
                var thisNode = openList.Pop();
                curIndex = thisNode.gridIndex;
                PfProfilerEndSample();
                PfProfilerBeginSample("Open cell");
                if (calcGrid[curIndex].status == statusClosedValue)
                {
                    PfProfilerEndSample();
                }
                else
                {
#if DEBUG
                    calcGrid[curIndex].timesPopped++;
#endif
                    curIntVec3 = cellIndices.IndexToCell(curIndex);
                    if (DebugViewSettings.drawPaths && !disableDebugFlash && debug_openCellsPopped < 20000)
                    {
                        //draw backpointer
                        var    arrow    = GetBackPointerArrow(cellIndices.IndexToCell(calcGrid[curIndex].parentIndex), curIntVec3);
                        string leading  = "";
                        string trailing = "";

#if DEBUG
                        switch (calcGrid[curIndex].timesPopped)
                        {
                        case 1:
                            trailing = "\n\n";                                     // $"\n\n\n{thisNode.totalCostEstimate}({calcGrid[curIndex].knownCost + calcGrid[curIndex].originalHeuristicCost})";
                            break;

                        case 2:
                            trailing = "\n"; break;

                        case 3: break;

                        case 4:
                            leading = "\n"; break;

                        default:
                            leading = "\n\n"; break;
                        }
#endif
                        DebugFlash(curIntVec3, calcGrid[curIndex].knownCost / 1500f, leading + calcGrid[curIndex].knownCost + " " + arrow + " " + debug_openCellsPopped + trailing);
                    }
                    if (curIndex == destinationIndex || (!destinationIsOneCell && destinationRect.Contains(curIntVec3)))
                    {
                        PfProfilerEndSample();
                        PfProfilerBeginSample("Finalize Path");
                        var ret = FinalizedPath(curIndex);
                        PfProfilerEndSample();
                        return(ret);
                    }
                    //With reopening closed nodes, this limit can be reached a lot more easily. I've left it as is because it gets users to report bad paths.
                    if (closedCellCount > 160000)
                    {
                        Log.Warning(string.Concat(pawn, " pathing from ", start, " to ", dest, " hit search limit of ", 160000, " cells."));
                        PfProfilerEndSample();
                        return(PawnPath.NotFound);
                    }
                    PfProfilerEndSample();
                    PfProfilerBeginSample("Neighbor consideration");
                    for (int i = 0; i < 8; i++)
                    {
                        neighIndexes[i] = -1;

                        neighX = (ushort)(curIntVec3.x + Directions[i]);
                        neighZ = (ushort)(curIntVec3.z + Directions[i + 8]);
                        if (neighX >= mapSizeX || neighZ >= mapSizeZ)
                        {
                            continue;
                        }

                        switch (i)
                        {
                        case 4:     //Northeast
                            if (!pathGridDirect.WalkableExtraFast(curIndex - mapSizeX) || !pathGridDirect.WalkableExtraFast(curIndex + 1))
                            {
                                continue;
                            }
                            break;

                        case 5:     //Southeast
                            if (!pathGridDirect.WalkableExtraFast(curIndex + mapSizeX) || !pathGridDirect.WalkableExtraFast(curIndex + 1))
                            {
                                continue;
                            }
                            break;

                        case 6:     //Southwest
                            if (!pathGridDirect.WalkableExtraFast(curIndex + mapSizeX) || !pathGridDirect.WalkableExtraFast(curIndex - 1))
                            {
                                continue;
                            }
                            break;

                        case 7:     //Northwest
                            if (!pathGridDirect.WalkableExtraFast(curIndex - mapSizeX) || !pathGridDirect.WalkableExtraFast(curIndex - 1))
                            {
                                continue;
                            }
                            break;
                        }

                        neighIndex = cellIndices.CellToIndex(neighX, neighZ);

                        if ((calcGrid[neighIndex].status != statusClosedValue) && (calcGrid[neighIndex].status != statusOpenValue))
                        {
                            if (10000 <= (calcGrid[neighIndex].perceivedPathCost = GetTotalPerceivedPathCost(traverseParms, canPassAnything, shouldCollideWithPawns, pawn, pawnPathCosts)))
                            {
                                continue;
                            }
#if DEBUG
                            calcGrid[neighIndex].timesPopped = 0;
#endif
                            #region heuristic
                            PfProfilerBeginSample("Heuristic");
                            switch (mode)
                            {
                            case HeuristicMode.Vanilla:
                                h = heuristicStrength * (Math.Abs(neighX - destinationX) + Math.Abs(neighZ - destinationZ));
                                break;

                            case HeuristicMode.AdmissableOctile:
                            {
                                var dx = Math.Abs(neighX - destinationX);
                                var dy = Math.Abs(neighZ - destinationZ);
                                h = moveTicksCardinal * (dx + dy) + (moveTicksDiagonal - 2 * moveTicksCardinal) * Math.Min(dx, dy);
                            }
                            break;

                            case HeuristicMode.Better:
                                if (canPassAnything)
                                {
                                    var dx = Math.Abs(neighX - destinationX);
                                    var dy = Math.Abs(neighZ - destinationZ);
                                    h = heuristicStrength * (moveTicksCardinal * (dx + dy) + (moveTicksDiagonal - 2 * moveTicksCardinal) * Math.Min(dx, dy));
                                }
                                else
                                {
                                    h = regionCost.GetPathCostToRegion(neighIndex);
                                }
                                break;
                            }
                            calcGrid[neighIndex].heuristicCost = h;
#if PATHMAX
                            calcGrid[neighIndex].originalHeuristicCost = h;
#endif
                            PfProfilerEndSample();
                            #endregion
                        }


                        if (calcGrid[neighIndex].perceivedPathCost < 10000)
                        {
                            neighIndexes[i] = neighIndex;
                        }
                        if (mode == HeuristicMode.Better && (calcGrid[neighIndex].status == statusOpenValue &&
                                                             Math.Max(i > 3 ? (int)(calcGrid[curIndex].perceivedPathCost * diagonalPerceivedCostWeight) + moveTicksDiagonal : calcGrid[curIndex].perceivedPathCost + moveTicksCardinal, 1) + calcGrid[neighIndex].knownCost < calcGrid[curIndex].knownCost))
                        {
                            calcGrid[curIndex].parentIndex = neighIndex;
                            calcGrid[curIndex].knownCost   = Math.Max(i > 3 ? (int)(calcGrid[curIndex].perceivedPathCost * diagonalPerceivedCostWeight) + moveTicksDiagonal : calcGrid[curIndex].perceivedPathCost + moveTicksCardinal, 1) + calcGrid[neighIndex].knownCost;
                        }
                    }
                    #region BPMX Best H
#if PATHMAX
                    PfProfilerBeginSample("BPMX Best H");
                    int bestH = calcGrid[curIndex].heuristicCost;
                    if (mode == HeuristicMode.Better && pathmaxEnabled)
                    {
                        for (int i = 0; i < 8; i++)
                        {
                            neighIndex = neighIndexes[i];
                            if (neighIndex < 0)
                            {
                                continue;
                            }
                            bestH = Math.Max(bestH, calcGrid[neighIndex].heuristicCost - (calcGrid[curIndex].perceivedPathCost + (i > 3 ? moveTicksDiagonal : moveTicksCardinal)));
                        }
                    }

                    //Pathmax Rule 3: set the current node heuristic to the best value of all connected nodes
                    calcGrid[curIndex].heuristicCost = bestH;
                    PfProfilerEndSample();
#endif
                    #endregion

                    #region Updating open list
                    for (int i = 0; i < 8; i++)
                    {
                        neighIndex = neighIndexes[i];
                        if (neighIndex < 0)
                        {
                            continue;
                        }
                        if (calcGrid[neighIndex].status == statusClosedValue && (canPassAnything || mode != HeuristicMode.Better))
                        {
                            continue;
                        }

                        //When path costs are significantly higher than move costs (e.g. snowy ice, or outside of allowed areas),
                        //small differences in the weighted heuristic overwhelm the added cost of diagonal movement, so nodes
                        //can often be visited in unnecessary zig-zags, causing lots of nodes to be reopened later, and weird looking
                        //paths if they are not revisited. Weighting the diagonal path cost slightly counteracts this behavior, and
                        //should result in natural looking paths when it does cause suboptimal behavior
                        var thisDirEdgeCost = (i > 3 ? (int)(calcGrid[neighIndex].perceivedPathCost * diagonalPerceivedCostWeight) + moveTicksDiagonal : calcGrid[neighIndex].perceivedPathCost + moveTicksCardinal);

                        //var thisDirEdgeCost = calcGrid[neighIndex].perceivedPathCost + (i > 3 ? moveTicksDiagonal : moveTicksCardinal);
                        //Some mods can result in negative path costs. That works well enough with Vanilla, since it won't revisit closed nodes, but when we do, it's an infinite loop.
                        thisDirEdgeCost     = (ushort)Math.Max(thisDirEdgeCost, 1);
                        neighCostThroughCur = thisDirEdgeCost + calcGrid[curIndex].knownCost;
#if PATHMAX
                        //Pathmax Rule 1
                        int nodeH = (mode == HeuristicMode.Better && pathmaxEnabled) ? Math.Max(calcGrid[neighIndex].heuristicCost, bestH - thisDirEdgeCost) : calcGrid[neighIndex].heuristicCost;
#endif
                        if (calcGrid[neighIndex].status == statusClosedValue || calcGrid[neighIndex].status == statusOpenValue)
                        {
#if PATHMAX
                            bool needsUpdate = false;
#endif
                            int minReopenGain = 0;
                            if (calcGrid[neighIndex].status == statusOpenValue)
                            {
#if PATHMAX
                                needsUpdate = nodeH > calcGrid[neighIndex].heuristicCost;
#endif
                            }
                            else
                            {                                   //Don't reopen closed nodes if the path cost difference isn't large enough to justify it; otherwise there can be cascades of revisiting the same nodes over and over for tiny path improvements each time
                                                                //Increasing the threshold as more cells get reopened further helps prevent cascades
                                minReopenGain = moveTicksCardinal + closedCellsReopened / 5;
                                if (pawnPathCosts.area?[neighIndex] == false)
                                {
                                    minReopenGain *= 10;
                                }
                            }
#if PATHMAX
                            calcGrid[neighIndex].heuristicCost = nodeH;
#endif
                            if (!(neighCostThroughCur + minReopenGain < calcGrid[neighIndex].knownCost))
                            {
#if PATHMAX
                                if (needsUpdate)                                 //if the heuristic cost was increased for an open node, we need to adjust its spot in the queue
                                {
                                    var neighCell = cellIndices.IndexToCell(neighIndex);
                                    var edgeCost  = Math.Max(calcGrid[neighIndex].parentX != neighCell.x && calcGrid[neighIndex].parentZ != neighCell.z ? (int)(calcGrid[neighIndex].perceivedPathCost * diagonalPercievedCostWeight) + moveTicksDiagonal : calcGrid[neighIndex].perceivedPathCost + moveTicksCardinal, 1);
                                    openList.PushOrUpdate(new CostNode(neighIndex, calcGrid[neighIndex].knownCost - edgeCost
                                                                       + (int)Math.Ceiling((edgeCost + nodeH) * regionHeuristicWeight.Evaluate(calcGrid[neighIndex].knownCost))));
                                }
#endif
                                continue;
                            }
                            if (calcGrid[neighIndex].status == statusClosedValue)
                            {
                                closedCellsReopened++;
                            }
                        }
                        //else
                        //{
                        //	DebugFlash(cellIndices.IndexToCell(neighIndex), 0.2f, $"\n\n{neighCostThroughCur} | {nodeH}\n{calcGrid[curIndex].knownCost + (int)Math.Ceiling((nodeH + thisDirEdgeCost) * regionHeuristicWeight.Evaluate(calcGrid[curIndex].knownCost))}");
                        //}

                        calcGrid[neighIndex].parentIndex = curIndex;
                        calcGrid[neighIndex].knownCost   = neighCostThroughCur;
                        calcGrid[neighIndex].status      = statusOpenValue;
#if PATHMAX
                        calcGrid[neighIndex].heuristicCost = nodeH;
#endif
                        PfProfilerBeginSample("Push Open");
                        openList.PushOrUpdate(new CostNode(neighIndex, calcGrid[curIndex].knownCost
                                                           + (int)Math.Ceiling((calcGrid[neighIndex].heuristicCost + thisDirEdgeCost) * regionHeuristicWeight.Evaluate(calcGrid[curIndex].knownCost))));
                        debug_totalOpenListCount++;
                        PfProfilerEndSample();
                    }
                    #endregion
                    PfProfilerEndSample();
                    closedCellCount++;
                    calcGrid[curIndex].status = statusClosedValue;
                }
            }
            if (!debug_pathFailMessaged)
            {
                string text  = pawn?.CurJob?.ToString() ?? "null";
                string text2 = pawn?.Faction?.ToString() ?? "null";
                Log.Warning(string.Concat(pawn, " pathing from ", start, " to ", dest, " ran out of cells to process.\nJob:", text, "\nFaction: ", text2));
                debug_pathFailMessaged = true;
            }
            PfProfilerEndSample();
            return(PawnPath.NotFound);
        }
示例#10
0
        private static bool CanReach(Thing searcher, Thing target, bool canBash)
        {
            Pawn pawn = searcher as Pawn;

            if (pawn != null)
            {
                if (!pawn.CanReach(target, PathEndMode.Touch, Danger.Some, canBash, TraverseMode.ByPawn))
                {
                    return(false);
                }
            }
            else
            {
                TraverseMode mode = (TraverseMode)(canBash ? 1 : 2);
                if (!searcher.Map.reachability.CanReach(searcher.Position, target, PathEndMode.Touch, TraverseParms.For(mode, Danger.Deadly, false)))
                {
                    return(false);
                }
            }
            return(true);
        }
示例#11
0
 private static Thing FindClosestReachable(Pawn p, Predicate <Thing> validator)
 {
     return(GenClosest.ClosestThingReachable(p.Position, p.Map, ThingRequest.ForGroup(ThingRequestGroup.HaulableEver), PathEndMode.Touch, TraverseParms.For(p, Danger.Deadly, TraverseMode.ByPawn, false), 9999f, validator, null, 0, -1, false, RegionType.Set_Passable, false));
 }
示例#12
0
        public static Building_BioReactor FindBioReactorFor(Pawn p, Pawn traveler, bool ignoreOtherReservations = false)
        {
            IEnumerable <ThingDef> enumerable = from def in DefDatabase <ThingDef> .AllDefs
                                                where typeof(Building_BioReactor).IsAssignableFrom(def.thingClass)
                                                select def;

            foreach (ThingDef singleDef in enumerable)
            {
                Building_BioReactor building_BioReactor = (Building_BioReactor)GenClosest.ClosestThingReachable(p.Position, p.Map, ThingRequest.ForDef(singleDef), PathEndMode.InteractionCell, TraverseParms.For(traveler, Danger.Deadly, TraverseMode.ByPawn, false), 9999f, delegate(Thing x)
                {
                    bool result;
                    if (!((Building_BioReactor)x).HasAnyContents)
                    {
                        Pawn traveler2                = traveler;
                        LocalTargetInfo target        = x;
                        bool ignoreOtherReservations2 = ignoreOtherReservations;
                        result = traveler2.CanReserve(target, 1, -1, null, ignoreOtherReservations2);
                    }
                    else
                    {
                        result = false;
                    }
                    return(result);
                }, null, 0, -1, false, RegionType.Set_Passable, false);
                if (building_BioReactor != null && !building_BioReactor.forbiddable.Forbidden)
                {
                    if ((p.BodySize <= ((BioReactorDef)(building_BioReactor.def)).bodySizeMax) && (p.BodySize >= ((BioReactorDef)(building_BioReactor.def)).bodySizeMin))
                    {
                        return(building_BioReactor);
                    }
                }
            }
            return(null);
        }
        public override void CompTick()
        {
            base.CompTick();

            if (AlphaAnimalsEvents_Settings.flagHelixienCorpseEffect)
            {
                tickCounter++;
                if (tickCounter > Props.tickInterval)
                {
                    Pawn pawn = this.parent as Pawn;
                    if (pawn.Map != null)
                    {
                        CellRect rect = GenAdj.OccupiedRect(pawn.Position, pawn.Rotation, IntVec2.One);
                        rect = rect.ExpandedBy(Props.radius);

                        foreach (IntVec3 current in rect.Cells)
                        {
                            if (current.InBounds(pawn.Map))
                            {
                                HashSet <Thing> hashSet = new HashSet <Thing>(current.GetThingList(pawn.Map));
                                if (hashSet != null)
                                {
                                    foreach (Thing thingInCell in hashSet)
                                    {
                                        Corpse corpse = thingInCell as Corpse;
                                        if (corpse != null)
                                        {
                                            if (corpse.InnerPawn.def.race.IsFlesh)
                                            {
                                                corpse.HitPoints         -= 5;
                                                pawn.needs.food.CurLevel += Props.nutritionGained;

                                                if ((pawn.Faction == Faction.OfPlayer) && (corpse.InnerPawn.def.race.Humanlike))
                                                {
                                                    pawn.health.AddHediff(HediffDef.Named("AA_CorpseFeast"));
                                                }


                                                CompRottable compRottable = corpse.TryGetComp <CompRottable>();
                                                if (compRottable.Stage == RotStage.Fresh)
                                                {
                                                    compRottable.RotProgress += 100000;
                                                }

                                                if (corpse.HitPoints < 0)
                                                {
                                                    corpse.Destroy(DestroyMode.Vanish);
                                                    for (int i = 0; i < 20; i++)
                                                    {
                                                        IntVec3 c;
                                                        CellFinder.TryFindRandomReachableCellNear(pawn.Position, pawn.Map, 2, TraverseParms.For(TraverseMode.NoPassClosedDoors, Danger.Deadly, false), null, null, out c);
                                                        FilthMaker.TryMakeFilth(c, pawn.Map, ThingDefOf.Filth_CorpseBile, pawn.LabelIndefinite(), 1, FilthSourceFlags.None);
                                                        SoundDef.Named(Props.corpseSound).PlayOneShot(new TargetInfo(pawn.Position, pawn.Map, false));
                                                    }
                                                }
                                                FilthMaker.TryMakeFilth(current, pawn.Map, ThingDefOf.Filth_CorpseBile, pawn.LabelIndefinite(), 1, FilthSourceFlags.None);
                                                flagOnce = true;
                                            }
                                        }
                                    }
                                }
                            }
                            if (flagOnce)
                            {
                                flagOnce = false; break;
                            }
                        }
                    }



                    tickCounter = 0;
                }
            }
        }
示例#14
0
        private static bool TryFindBestBillIngredients(Pawn pawn, Building_CokeFurnace billGiver, List <ThingCount> chosen)
        {
            chosen.Clear();
            newRelevantThings.Clear();
            if (billGiver.SelectedRecipe.ingredients.Count == 0)
            {
                return(true);
            }
            IntVec3 rootCell = GetBillGiverRootCell(billGiver, pawn);
            Region  rootReg  = rootCell.GetRegion(pawn.Map);

            if (rootReg == null)
            {
                return(false);
            }
            MakeIngredientsListInProcessingOrder(ingredientsOrdered, billGiver);
            relevantThings.Clear();
            processedThings.Clear();
            bool foundAll = false;
            Predicate <Thing>    baseValidator  = (Thing t) => t.Spawned && !t.IsForbidden(pawn) && (float)(t.Position - billGiver.Position).LengthHorizontalSquared < 9999f && pawn.CanReserve(t);
            TraverseParms        traverseParams = TraverseParms.For(pawn);
            RegionEntryPredicate entryCondition = (Region from, Region r) => r.Allows(traverseParams, isDestination: false);
            int adjacentRegionsAvailable        = rootReg.Neighbors.Count((Region region) => entryCondition(rootReg, region));
            int regionsProcessed = 0;

            processedThings.AddRange(relevantThings);
            RegionProcessor regionProcessor = delegate(Region r)
            {
                List <Thing> list = r.ListerThings.ThingsMatching(ThingRequest.ForGroup(ThingRequestGroup.HaulableEver));
                for (int i = 0; i < list.Count; i++)
                {
                    Thing thing = list[i];
                    if (!processedThings.Contains(thing) && ReachabilityWithinRegion.ThingFromRegionListerReachable(thing, r, PathEndMode.ClosestTouch, pawn) && baseValidator(thing) && !thing.def.IsMedicine)
                    {
                        newRelevantThings.Add(thing);
                        processedThings.Add(thing);
                    }
                }
                regionsProcessed++;
                if (newRelevantThings.Count > 0 && regionsProcessed > adjacentRegionsAvailable)
                {
                    Comparison <Thing> comparison = delegate(Thing t1, Thing t2)
                    {
                        float num   = (t1.Position - rootCell).LengthHorizontalSquared;
                        float value = (t2.Position - rootCell).LengthHorizontalSquared;
                        return(num.CompareTo(value));
                    };
                    newRelevantThings.Sort(comparison);
                    relevantThings.AddRange(newRelevantThings);
                    newRelevantThings.Clear();
                    if (TryFindBestBillIngredientsInSet(relevantThings, billGiver, chosen))
                    {
                        foundAll = true;
                        return(true);
                    }
                }
                return(false);
            };

            RegionTraverser.BreadthFirstTraverse(rootReg, entryCondition, regionProcessor, 99999);
            relevantThings.Clear();
            newRelevantThings.Clear();
            processedThings.Clear();
            ingredientsOrdered.Clear();
            return(foundAll);
        }
 private static bool TryRandomNonOccupiedClosewalkCellNear(IntVec3 root, Map map, int radius, out IntVec3 result)
 {
     return(CellFinder.TryFindRandomReachableCellNear(root, map, (float)radius, TraverseParms.For(TraverseMode.NoPassClosedDoors, Danger.Deadly, false), (Predicate <IntVec3>)((IntVec3 c) => c.Standable(map) && c.GetFirstPawn(map) == null), (Predicate <Region>)null, out result, 999999));
 }
示例#16
0
        private List <IntVec3> RefineEndcap(List <IntVec3> input, Map map)
        {
            float[] array = new float[endcapSamples.Length];
            for (int i = 0; i < endcapSamples.Length; i++)
            {
                int      index    = Mathf.RoundToInt((float)input.Count * endcapSamples[i]);
                PawnPath pawnPath = map.pathFinder.FindPath(input[index], input[input.Count - 1], TraverseParms.For(TraverseMode.NoPassClosedDoorsOrWater));
                if (pawnPath == PawnPath.NotFound)
                {
                    pawnPath = map.pathFinder.FindPath(input[index], input[input.Count - 1], TraverseParms.For(TraverseMode.NoPassClosedDoors));
                }
                if (pawnPath == PawnPath.NotFound)
                {
                    pawnPath = map.pathFinder.FindPath(input[index], input[input.Count - 1], TraverseParms.For(TraverseMode.PassAllDestroyableThingsNotWater));
                }
                if (pawnPath == PawnPath.NotFound)
                {
                    pawnPath = map.pathFinder.FindPath(input[index], input[input.Count - 1], TraverseParms.For(TraverseMode.PassAllDestroyableThings));
                }
                if (pawnPath != null && pawnPath != PawnPath.NotFound)
                {
                    array[i] = pawnPath.TotalCost;
                }
                pawnPath.ReleaseToPool();
            }
            float   num   = 0f;
            int     num2  = 0;
            IntVec3 start = IntVec3.Invalid;

            for (int j = 0; j < 2; j++)
            {
                IntVec3 facingCell = new Rot4(j).FacingCell;
                IntVec3 intVec     = input[input.Count - 1];
                bool    flag       = true;
                if (Mathf.Abs(intVec.x * facingCell.x) > 5 && Mathf.Abs(intVec.x * facingCell.x - map.Size.x) > 5)
                {
                    flag = false;
                }
                if (Mathf.Abs(intVec.z * facingCell.z) > 5 && Mathf.Abs(intVec.z * facingCell.z - map.Size.z) > 5)
                {
                    flag = false;
                }
                if (!flag)
                {
                    continue;
                }
                for (int k = 0; k < endcapSamples.Length; k++)
                {
                    if (array[k] == 0f)
                    {
                        continue;
                    }
                    int     num3    = Mathf.RoundToInt((float)input.Count * endcapSamples[k]);
                    IntVec3 intVec2 = input[num3];
                    if (facingCell.x != 0)
                    {
                        intVec2.x = intVec.x;
                    }
                    else if (facingCell.z != 0)
                    {
                        intVec2.z = intVec.z;
                    }
                    PawnPath pawnPath2 = map.pathFinder.FindPath(input[num3], input[input.Count - 1], TraverseParms.For(TraverseMode.NoPassClosedDoors));
                    if (pawnPath2 == PawnPath.NotFound)
                    {
                        pawnPath2 = map.pathFinder.FindPath(input[num3], input[input.Count - 1], TraverseParms.For(TraverseMode.PassAllDestroyableThings));
                    }
                    if (pawnPath2 != PawnPath.NotFound)
                    {
                        float num4 = array[k] / pawnPath2.TotalCost;
                        if (num4 > num)
                        {
                            num   = num4;
                            num2  = num3;
                            start = intVec2;
                        }
                        pawnPath2.ReleaseToPool();
                    }
                }
            }
            input = new List <IntVec3>(input);
            if ((double)num > 1.75)
            {
                using (PawnPath pawnPath3 = map.pathFinder.FindPath(start, input[num2], TraverseParms.For(TraverseMode.NoPassClosedDoors)))
                {
                    input.RemoveRange(num2, input.Count - num2);
                    input.AddRange(pawnPath3.NodesReversed);
                    return(input);
                }
            }
            return(input);
        }
示例#17
0
        protected override Job TryGiveJob(Pawn pawn)
        {
            if (lastTickTantrumed > Find.TickManager.TicksGame - 2000 || Rand.Value < 0.5f)
            {
                return(null);
            }
            Predicate <Thing> validator = delegate(Thing t)
            {
                return(!t.IsBurning() && t.def.useHitPoints);
            };
            Building building = (Building)GenClosest.ClosestThingReachable(pawn.Position, pawn.Map, ThingRequest.ForGroup(ThingRequestGroup.BuildingArtificial), PathEndMode.Touch, TraverseParms.For(TraverseMode.ByPawn, Danger.Deadly, true), 9999f, validator, null, -1, false);

            if (building != null)
            {
                lastTickTantrumed = Find.TickManager.TicksGame;
                int maxNumMeleeAttacks = Rand.RangeInclusive(10, 30) + (Rand.Value < 0.1f ? Rand.RangeInclusive(10, 30) : 0);
                pawn.guilt.Notify_Guilty();
                return(new Job(JobDefOf.AttackMelee, building)
                {
                    maxNumMeleeAttacks = maxNumMeleeAttacks,
                    expiryInterval = 50000,
                    canBash = true
                });
            }
            return(null);
        }
示例#18
0
        private IntVec3 FindRoadExitCell(Map map, float angle, IntVec3 crossroads, ref RoadPathingDef pathingDef)
        {
            Predicate <IntVec3> tileValidator = delegate(IntVec3 pos)
            {
                foreach (IntVec3 item in GenRadial.RadialCellsAround(pos, 8f, useCenter: true))
                {
                    if (item.InBounds(map) && item.GetTerrain(map).IsWater)
                    {
                        return(false);
                    }
                }
                return(true);
            };
            IntVec3 result;

            for (float validAngleSpan2 = 10f; validAngleSpan2 < 90f; validAngleSpan2 += 10f)
            {
                Predicate <IntVec3> angleValidator2 = (IntVec3 pos) => GenGeo.AngleDifferenceBetween((pos - map.Center).AngleFlat, angle) < validAngleSpan2;
                if (CellFinder.TryFindRandomEdgeCellWith((IntVec3 x) => angleValidator2(x) && tileValidator(x) && map.reachability.CanReach(crossroads, x, PathEndMode.OnCell, TraverseParms.For(TraverseMode.NoPassClosedDoors)), map, 0f, out result))
                {
                    return(result);
                }
            }
            if (pathingDef == RoadPathingDefOf.Avoid)
            {
                pathingDef = RoadPathingDefOf.Bulldoze;
            }
            for (float validAngleSpan = 10f; validAngleSpan < 90f; validAngleSpan += 10f)
            {
                Predicate <IntVec3> angleValidator = (IntVec3 pos) => GenGeo.AngleDifferenceBetween((pos - map.Center).AngleFlat, angle) < validAngleSpan;
                if (CellFinder.TryFindRandomEdgeCellWith((IntVec3 x) => angleValidator(x) && tileValidator(x) && map.reachability.CanReach(crossroads, x, PathEndMode.OnCell, TraverseParms.For(TraverseMode.PassAllDestroyableThings)), map, 0f, out result))
                {
                    return(result);
                }
            }
            Log.Error($"Can't find exit from map from {crossroads} to angle {angle}");
            return(IntVec3.Invalid);
        }
 protected override bool CanScatterAt(IntVec3 c, Map map)
 {
     return(map.reachability.CanReachMapEdge(c, TraverseParms.For(TraverseMode.PassDoors, Danger.Deadly, false)));
 }
示例#20
0
        private Thing FindDrugFor(Pawn pawn, Need_Chemical need)
        {
            Hediff_Addiction addictionHediff = need.AddictionHediff;
            Thing            result;

            if (addictionHediff == null)
            {
                result = null;
            }
            else
            {
                ThingOwner <Thing> innerContainer = pawn.inventory.innerContainer;
                for (int i = 0; i < innerContainer.Count; i++)
                {
                    if (this.DrugValidator(pawn, addictionHediff, innerContainer[i]))
                    {
                        return(innerContainer[i]);
                    }
                }
                result = GenClosest.ClosestThingReachable(pawn.Position, pawn.Map, ThingRequest.ForGroup(ThingRequestGroup.Drug), PathEndMode.ClosestTouch, TraverseParms.For(pawn, Danger.Deadly, TraverseMode.ByPawn, false), 9999f, (Thing x) => this.DrugValidator(pawn, addictionHediff, x), null, 0, -1, false, RegionType.Set_Passable, false);
            }
            return(result);
        }
        public static Thing FindThingToHaul(Pawn p, Lord lord)
        {
            neededItems.Clear();
            List <TransferableOneWay> transferables = ((LordJob_FormAndSendCaravan)lord.LordJob).transferables;

            for (int i = 0; i < transferables.Count; i++)
            {
                TransferableOneWay transferableOneWay = transferables[i];
                if (CountLeftToTransfer(p, transferableOneWay, lord) > 0)
                {
                    for (int j = 0; j < transferableOneWay.things.Count; j++)
                    {
                        neededItems.Add(transferableOneWay.things[j]);
                    }
                }
            }
            if (!neededItems.Any())
            {
                return(null);
            }
            Thing result = GenClosest.ClosestThingReachable(p.Position, p.Map, ThingRequest.ForGroup(ThingRequestGroup.HaulableEver), PathEndMode.Touch, TraverseParms.For(p), 9999f, (Thing x) => neededItems.Contains(x) && p.CanReserve(x));

            neededItems.Clear();
            return(result);
        }
示例#22
0
        public static Toil CarryIngestibleToChewSpot(Pawn pawn, TargetIndex ingestibleInd)
        {
            Toil toil = new Toil();

            toil.initAction = delegate
            {
                Pawn              actor              = toil.actor;
                IntVec3           intVec             = IntVec3.Invalid;
                Thing             thing              = null;
                Thing             thing2             = actor.CurJob.GetTarget(ingestibleInd).Thing;
                Predicate <Thing> baseChairValidator = delegate(Thing t)
                {
                    if (t.def.building == null || !t.def.building.isSittable)
                    {
                        return(false);
                    }
                    if (t.IsForbidden(pawn))
                    {
                        return(false);
                    }
                    if (!actor.CanReserve(t))
                    {
                        return(false);
                    }
                    if (!t.IsSociallyProper(actor))
                    {
                        return(false);
                    }
                    if (t.IsBurning())
                    {
                        return(false);
                    }
                    if (t.HostileTo(pawn))
                    {
                        return(false);
                    }
                    bool flag = false;
                    for (int i = 0; i < 4; i++)
                    {
                        IntVec3  c       = t.Position + GenAdj.CardinalDirections[i];
                        Building edifice = c.GetEdifice(t.Map);
                        if (edifice != null && edifice.def.surfaceType == SurfaceType.Eat)
                        {
                            flag = true;
                            break;
                        }
                    }
                    if (!flag)
                    {
                        return(false);
                    }
                    return(true);
                };
                if (thing2.def.ingestible.chairSearchRadius > 0f)
                {
                    thing = GenClosest.ClosestThingReachable(actor.Position, actor.Map, ThingRequest.ForGroup(ThingRequestGroup.BuildingArtificial), PathEndMode.OnCell, TraverseParms.For(actor), thing2.def.ingestible.chairSearchRadius, (Thing t) => baseChairValidator(t) && t.Position.GetDangerFor(pawn, t.Map) == Danger.None);
                }
                if (thing == null)
                {
                    intVec = RCellFinder.SpotToChewStandingNear(actor, actor.CurJob.GetTarget(ingestibleInd).Thing);
                    Danger chewSpotDanger = intVec.GetDangerFor(pawn, actor.Map);
                    if (chewSpotDanger != Danger.None)
                    {
                        thing = GenClosest.ClosestThingReachable(actor.Position, actor.Map, ThingRequest.ForGroup(ThingRequestGroup.BuildingArtificial), PathEndMode.OnCell, TraverseParms.For(actor), thing2.def.ingestible.chairSearchRadius, (Thing t) => baseChairValidator(t) && (int)t.Position.GetDangerFor(pawn, t.Map) <= (int)chewSpotDanger);
                    }
                }
                if (thing != null)
                {
                    intVec = thing.Position;
                    actor.Reserve(thing, actor.CurJob);
                }
                actor.Map.pawnDestinationReservationManager.Reserve(actor, actor.CurJob, intVec);
                actor.pather.StartPath(intVec, PathEndMode.OnCell);
            };
            toil.defaultCompleteMode = ToilCompleteMode.PatherArrival;
            return(toil);
        }
示例#23
0
        /// <summary>
        /// Figures out the best location to use this Ability at. Default implementation returns the enemy target, closest ally or the caster.
        /// </summary>
        /// <param name="abilityDef">Ability Def for the AI.</param>
        /// <param name="pawn">Pawn to take in account.</param>
        /// <returns>Targeting location or Pawn.</returns>
        public virtual LocalTargetInfo TargetAbilityFor(AbilityAIDef abilityDef, Pawn pawn)
        {
            if (abilityDef.usedOnCaster)
            {
                return(pawn);
            }
            else
            if (abilityDef.canTargetAlly)
            {
                return(GenClosest.ClosestThingReachable(pawn.Position, pawn.Map, ThingRequest.ForGroup(ThingRequestGroup.Pawn), Verse.AI.PathEndMode.OnCell, TraverseParms.For(TraverseMode.NoPassClosedDoors), abilityDef.maxRange, thing => AbilityUtility.AreAllies(pawn, thing)));
            }
            else
            if (pawn.mindState.enemyTarget != null && pawn.mindState.enemyTarget is Pawn targetPawn)
            {
                if (!targetPawn.Dead)
                {
                    return(pawn.mindState.enemyTarget);
                }
            }
            else
            {
                if (pawn.mindState.enemyTarget != null && !(pawn.mindState.enemyTarget is Corpse))
                {
                    return(pawn.mindState.enemyTarget);
                }
            }

            return(null);
        }
示例#24
0
        public static Thing findAmmo(Pawn pawn, AERIALSYSTEM aeriel)
        {
            StorageSettings   allowed   = pawn.IsColonist ? aeriel.gun.TryGetComp <AERIALChangeableProjectile>().allowedShellsSettings : null;
            Predicate <Thing> validator = (Thing t) => !t.IsForbidden(pawn) && pawn.CanReserve(t, 10, 1, null, false) && (allowed == null || allowed.AllowedToAccept(t));

            return(GenClosest.ClosestThingReachable(pawn.Position, pawn.Map, ThingRequest.ForGroup(ThingRequestGroup.Shell), PathEndMode.OnCell, TraverseParms.For(pawn, Danger.Deadly, TraverseMode.ByPawn, false), 40f, validator, null, 0, -1, false, RegionType.Set_Passable, false));
        }
示例#25
0
        public static Toil CarryIngestibleToChewSpot(Pawn pawn, TargetIndex ingestibleInd)
        {
            Toil toil = new Toil();

            toil.initAction = delegate
            {
                Pawn              actor              = toil.actor;
                IntVec3           cell2              = IntVec3.Invalid;
                Thing             thing              = null;
                Thing             thing2             = actor.CurJob.GetTarget(ingestibleInd).Thing;
                Predicate <Thing> baseChairValidator = delegate(Thing t)
                {
                    if (t.def.building == null || !t.def.building.isSittable)
                    {
                        return(false);
                    }
                    if (!TryFindFreeSittingSpotOnThing(t, out var _))
                    {
                        return(false);
                    }
                    if (t.IsForbidden(pawn))
                    {
                        return(false);
                    }
                    if (!actor.CanReserve(t))
                    {
                        return(false);
                    }
                    if (!t.IsSociallyProper(actor))
                    {
                        return(false);
                    }
                    if (t.IsBurning())
                    {
                        return(false);
                    }
                    if (t.HostileTo(pawn))
                    {
                        return(false);
                    }
                    bool flag = false;
                    for (int i = 0; i < 4; i++)
                    {
                        Building edifice = (t.Position + GenAdj.CardinalDirections[i]).GetEdifice(t.Map);
                        if (edifice != null && edifice.def.surfaceType == SurfaceType.Eat)
                        {
                            flag = true;
                            break;
                        }
                    }
                    return(flag ? true : false);
                };
                if (thing2.GetIngestibleProperties().chairSearchRadius > 0f)
                {
                    thing = GenClosest.ClosestThingReachable(actor.Position, actor.Map, ThingRequest.ForGroup(ThingRequestGroup.BuildingArtificial), PathEndMode.OnCell, TraverseParms.For(actor), thing2.GetIngestibleProperties().chairSearchRadius, (Thing t) => baseChairValidator(t) && t.Position.GetDangerFor(pawn, t.Map) == Danger.None);
                }
                if (thing == null)
                {
                    cell2 = RCellFinder.SpotToChewStandingNear(actor, actor.CurJob.GetTarget(ingestibleInd).Thing, (IntVec3 c) => actor.CanReserveSittableOrSpot(c));
                    Danger chewSpotDanger = cell2.GetDangerFor(pawn, actor.Map);
                    if (chewSpotDanger != Danger.None)
                    {
                        thing = GenClosest.ClosestThingReachable(actor.Position, actor.Map, ThingRequest.ForGroup(ThingRequestGroup.BuildingArtificial), PathEndMode.OnCell, TraverseParms.For(actor), thing2.GetIngestibleProperties().chairSearchRadius, (Thing t) => baseChairValidator(t) && (int)t.Position.GetDangerFor(pawn, t.Map) <= (int)chewSpotDanger);
                    }
                }
                if (thing != null && !TryFindFreeSittingSpotOnThing(thing, out cell2))
                {
                    Log.Error("Could not find sitting spot on chewing chair! This is not supposed to happen - we looked for a free spot in a previous check!");
                }
                actor.ReserveSittableOrSpot(cell2, actor.CurJob);
                actor.Map.pawnDestinationReservationManager.Reserve(actor, actor.CurJob, cell2);
                actor.pather.StartPath(cell2, PathEndMode.OnCell);
                bool TryFindFreeSittingSpotOnThing(Thing t, out IntVec3 cell)
                {
                    foreach (IntVec3 item in t.OccupiedRect())
                    {
                        if (actor.CanReserveSittableOrSpot(item))
                        {
                            cell = item;
                            return(true);
                        }
                    }
                    cell = default(IntVec3);
                    return(false);
                }
            };
            toil.defaultCompleteMode = ToilCompleteMode.PatherArrival;
            return(toil);
        }
        //Wrapper function to run extra testing/logging code.
        public PawnPath FindPath(IntVec3 start, LocalTargetInfo dest, TraverseParms traverseParms, PathEndMode peMode = PathEndMode.OnCell)
        {
#if DEBUG
            if (traverseParms.pawn != null)
            {
                Log.Message($"Pathfinding times for pawn {traverseParms.pawn}, mode: {traverseParms.mode}\n Move speed: {traverseParms.pawn.TicksPerMoveCardinal}, {traverseParms.pawn.TicksPerMoveDiagonal}");
            }
            disableDebugFlash = true;             //disable debug flash during timing tests
            var      sw          = new Stopwatch();
            PawnPath temp        = null;
            var      vanillaCost = float.MaxValue - 1000;
            diagonalPerceivedCostWeight = 1.0f;
            sw.Start();
            temp = FindPathInner(start, dest, traverseParms, peMode, HeuristicMode.Vanilla);
            sw.Stop();
            Log.Message("~~ Vanilla ~~ " + sw.ElapsedTicks + " ticks, " + debug_openCellsPopped + " open cells popped, " + temp.TotalCost + " path cost!");
            vanillaCost = temp.TotalCost;
            temp.Dispose();

            //sw.Reset();
            //sw.Start();
            //temp = FindPathInner(start, dest, traverseParms, peMode, HeuristicMode.AdmissableOctile);
            //sw.Stop();
            //Log.Message("~~ Admissable Octile ~~ " + sw.ElapsedTicks + " ticks, " + debug_openCellsPopped + " open cells popped, " + temp.TotalCost + " path cost!");
            //var optimal = temp.TotalCost;
            //temp.Dispose();

            try
            {
                diagonalPerceivedCostWeight = diagonalCostWeightSetting;
                sw.Reset();
                sw.Start();
                temp = FindPathInner(start, dest, traverseParms, peMode, HeuristicMode.Better);
                sw.Stop();
                Log.Message("~~ Better ~~ " + sw.ElapsedTicks + " ticks, " + debug_openCellsPopped + " open cells popped, " + temp.TotalCost + " path cost!  (" /*+ sw.ElapsedMilliseconds*/ + "ms)");
            }
            catch
            {
                if (Current.ProgramState == ProgramState.Playing)
                {
                    PathDataLog.SaveFromPathCall(this.map, start, dest, traverseParms, peMode);
                }
            }
            //var sb = new StringBuilder();
            //foreach (var pathmax in new [] {false, true})
            //{
            //	pathmaxEnabled = pathmax;
            //	foreach (var weight in new[] {false, true})
            //	{
            //		weightEnabled = weight;
            //		sw.Reset();
            //		sw.Start();
            //		temp = FindPathInner(start, dest, traverseParms, peMode);
            //		sw.Stop();
            //		sb.AppendLine($"pathmax: {pathmax}, weight: {weight}, pops: {debug_openCellsPopped}, pathcost: {temp.TotalCost}, elapsed: {sw.ElapsedTicks}");
            //		temp.Dispose();
            //	}
            //}
            //Log.Message(sb.ToString());

            //Log.Message("\t Distance Map Pops: " + RegionLinkDijkstra.nodes_popped);
            //Log.Message("\t Total open cells added: " + debug_totalOpenListCount);
            //Log.Message("\t Closed cells reopened: " + closedCellsReopened);
            //Log.Message($"\t Total Heuristic Estimate {debug_totalHeuristicCostEstimate}, off by {((temp.TotalCost / debug_totalHeuristicCostEstimate) - 1.0f).ToStringPercent()}");

            temp?.Dispose();
            disableDebugFlash = false;
#endif
#if PFPROFILE
            if (!hasRunOnce)
            {
                disableDebugFlash = true;
                var jitRun = FindPathInner(start, dest, traverseParms, peMode, HeuristicMode.Better);
                jitRun.Dispose();
                hasRunOnce        = true;
                disableDebugFlash = false;
            }
            sws.Clear();
#endif
            var result = FindPathInner(start, dest, traverseParms, peMode, HeuristicMode.Better);

#if PFPROFILE
            var profsb = new StringBuilder();
            foreach (var pfsw in sws)
            {
                profsb.AppendLine("SW " + pfsw.Key + ": " + pfsw.Value.ElapsedTicks.ToString("##,#") + " ticks.");
            }
            Log.Message(profsb.ToString());
#endif
#if DEBUG
            if (Current.ProgramState == ProgramState.Playing)
            {
                if (debug_openCellsPopped > 2500 || (vanillaCost + 100) < result.TotalCost || result == PawnPath.NotFound)
                {
                    PathDataLog.SaveFromPathCall(this.map, start, dest, traverseParms, peMode);
                }
            }
#endif
            return(result);
        }
示例#27
0
        public static IAttackTarget BestAttackTarget(IAttackTargetSearcher searcher, TargetScanFlags flags, Predicate <Thing> validator = null, float minDist = 0f, float maxDist = 9999f, IntVec3 locus = default(IntVec3), float maxTravelRadiusFromLocus = 3.40282347E+38f, bool canBash = false)
        {
            Thing searcherThing = searcher.Thing;
            Pawn  searcherPawn  = searcher as Pawn;
            Verb  verb          = searcher.CurrentEffectiveVerb;

            if (verb == null)
            {
                Log.Error("BestAttackTarget with " + searcher + " who has no attack verb.");
                return(null);
            }
            bool  onlyTargetMachines = verb != null && verb.IsEMP();
            float minDistanceSquared = minDist * minDist;
            float num = maxTravelRadiusFromLocus + verb.verbProps.range;
            float maxLocusDistSquared         = num * num;
            Func <IntVec3, bool> losValidator = null;

            if ((flags & TargetScanFlags.LOSBlockableByGas) != 0)
            {
                losValidator = delegate(IntVec3 vec3)
                {
                    Gas gas = vec3.GetGas(searcherThing.Map);
                    return(gas == null || !gas.def.gas.blockTurretTracking);
                };
            }
            Predicate <IAttackTarget> innerValidator = delegate(IAttackTarget t)
            {
                Thing thing = t.Thing;
                if (t == searcher)
                {
                    return(false);
                }
                if (minDistanceSquared > 0.0 && (float)(searcherThing.Position - thing.Position).LengthHorizontalSquared < minDistanceSquared)
                {
                    return(false);
                }
                if (maxTravelRadiusFromLocus < 9999.0 && (float)(thing.Position - locus).LengthHorizontalSquared > maxLocusDistSquared)
                {
                    return(false);
                }
                if (!searcherThing.HostileTo(thing))
                {
                    return(false);
                }
                if (validator != null && !validator(thing))
                {
                    return(false);
                }
                if ((flags & TargetScanFlags.NeedLOSToAll) != 0 && !searcherThing.CanSee(thing, losValidator))
                {
                    if (t is Pawn)
                    {
                        if ((flags & TargetScanFlags.NeedLOSToPawns) != 0)
                        {
                            return(false);
                        }
                    }
                    else if ((flags & TargetScanFlags.NeedLOSToNonPawns) != 0)
                    {
                        return(false);
                    }
                }
                if ((flags & TargetScanFlags.NeedThreat) != 0 && t.ThreatDisabled())
                {
                    return(false);
                }
                Pawn pawn2 = t as Pawn;
                if (onlyTargetMachines && pawn2 != null && pawn2.RaceProps.IsFlesh)
                {
                    return(false);
                }
                if ((flags & TargetScanFlags.NeedNonBurning) != 0 && thing.IsBurning())
                {
                    return(false);
                }
                if (searcherThing.def.race != null && (int)searcherThing.def.race.intelligence >= 2)
                {
                    CompExplosive compExplosive = thing.TryGetComp <CompExplosive>();
                    if (compExplosive != null && compExplosive.wickStarted)
                    {
                        return(false);
                    }
                }
                if (thing.def.size.x == 1 && thing.def.size.z == 1)
                {
                    if (thing.Position.Fogged(thing.Map))
                    {
                        return(false);
                    }
                }
                else
                {
                    bool flag2 = false;
                    CellRect.CellRectIterator iterator = thing.OccupiedRect().GetIterator();
                    while (!iterator.Done())
                    {
                        if (iterator.Current.Fogged(thing.Map))
                        {
                            iterator.MoveNext();
                            continue;
                        }
                        flag2 = true;
                        break;
                    }
                    if (!flag2)
                    {
                        return(false);
                    }
                }
                return(true);
            };

            if (AttackTargetFinder.HasRangedAttack(searcher))
            {
                AttackTargetFinder.tmpTargets.Clear();
                AttackTargetFinder.tmpTargets.AddRange(searcherThing.Map.attackTargetsCache.GetPotentialTargetsFor(searcher));
                if ((flags & TargetScanFlags.NeedReachable) != 0)
                {
                    Predicate <IAttackTarget> oldValidator = innerValidator;
                    innerValidator = ((IAttackTarget t) => oldValidator(t) && AttackTargetFinder.CanReach(searcherThing, t.Thing, canBash));
                }
                bool flag = false;
                if (searcherThing.Faction != Faction.OfPlayer)
                {
                    for (int i = 0; i < AttackTargetFinder.tmpTargets.Count; i++)
                    {
                        IAttackTarget attackTarget = AttackTargetFinder.tmpTargets[i];
                        if (attackTarget.Thing.Position.InHorDistOf(searcherThing.Position, maxDist) && innerValidator(attackTarget) && AttackTargetFinder.CanShootAtFromCurrentPosition(attackTarget, searcher, verb))
                        {
                            flag = true;
                            break;
                        }
                    }
                }
                IAttackTarget result;
                if (flag)
                {
                    AttackTargetFinder.tmpTargets.RemoveAll((IAttackTarget x) => !x.Thing.Position.InHorDistOf(searcherThing.Position, maxDist) || !innerValidator(x));
                    result = AttackTargetFinder.GetRandomShootingTargetByScore(AttackTargetFinder.tmpTargets, searcher, verb);
                }
                else
                {
                    Predicate <Thing> validator2 = ((flags & TargetScanFlags.NeedReachableIfCantHitFromMyPos) == TargetScanFlags.None || (flags & TargetScanFlags.NeedReachable) != 0) ? ((Predicate <Thing>)((Thing t) => innerValidator((IAttackTarget)t))) : ((Predicate <Thing>)((Thing t) => innerValidator((IAttackTarget)t) && (AttackTargetFinder.CanReach(searcherThing, t, canBash) || AttackTargetFinder.CanShootAtFromCurrentPosition((IAttackTarget)t, searcher, verb))));
                    result = (IAttackTarget)GenClosest.ClosestThing_Global(searcherThing.Position, AttackTargetFinder.tmpTargets, maxDist, validator2, null);
                }
                AttackTargetFinder.tmpTargets.Clear();
                return(result);
            }
            if (searcherPawn != null && searcherPawn.mindState.duty != null && searcherPawn.mindState.duty.radius > 0.0 && !searcherPawn.InMentalState)
            {
                Predicate <IAttackTarget> oldValidator2 = innerValidator;
                innerValidator = delegate(IAttackTarget t)
                {
                    if (!oldValidator2(t))
                    {
                        return(false);
                    }
                    if (!t.Thing.Position.InHorDistOf(searcherPawn.mindState.duty.focus.Cell, searcherPawn.mindState.duty.radius))
                    {
                        return(false);
                    }
                    return(true);
                };
            }
            IntVec3           root             = searcherThing.Position;
            Map               map              = searcherThing.Map;
            ThingRequest      thingReq         = ThingRequest.ForGroup(ThingRequestGroup.AttackTarget);
            PathEndMode       peMode           = PathEndMode.Touch;
            Pawn              pawn             = searcherPawn;
            Danger            maxDanger        = Danger.Deadly;
            bool              canBash2         = canBash;
            TraverseParms     traverseParams   = TraverseParms.For(pawn, maxDanger, TraverseMode.ByPawn, canBash2);
            float             maxDistance      = maxDist;
            Predicate <Thing> validator3       = (Thing x) => innerValidator((IAttackTarget)x);
            int               searchRegionsMax = (!(maxDist > 800.0)) ? 40 : (-1);
            IAttackTarget     attackTarget2    = (IAttackTarget)GenClosest.ClosestThingReachable(root, map, thingReq, peMode, traverseParams, maxDistance, validator3, null, 0, searchRegionsMax, false, RegionType.Set_Passable, false);

            if (attackTarget2 != null && PawnUtility.ShouldCollideWithPawns(searcherPawn))
            {
                IAttackTarget attackTarget3 = AttackTargetFinder.FindBestReachableMeleeTarget(innerValidator, searcherPawn, maxDist, canBash);
                if (attackTarget3 != null)
                {
                    root = searcherPawn.Position - attackTarget2.Thing.Position;
                    float lengthHorizontal  = root.LengthHorizontal;
                    float lengthHorizontal2 = (searcherPawn.Position - attackTarget3.Thing.Position).LengthHorizontal;
                    if (Mathf.Abs(lengthHorizontal - lengthHorizontal2) < 50.0)
                    {
                        attackTarget2 = attackTarget3;
                    }
                }
            }
            return(attackTarget2);
        }
        private static Pawn FindPawnTarget(Pawn pawn)
        {
            Pawn victim = null;

            bool Predicate(Thing p) => p != null && p != pawn &&
            p.Faction != pawn.Faction &&
            ((Pawn)p).health.hediffSet.GetFirstHediffOfDef(PurpleIvyDefOf.PI_MaskingSprayHigh) == null;

            const float distance = 25f;

            victim = (Pawn)GenClosest.ClosestThingReachable(pawn.Position,
                                                            pawn.Map, ThingRequest.ForGroup(ThingRequestGroup.Pawn), PathEndMode.Touch, TraverseParms.For(pawn, Danger.Deadly,
                                                                                                                                                          TraverseMode.PassDoors, false)
                                                            , distance, Predicate);
            return(victim);
        }
        private Job GetProductionBillJob(Pawn meeseeks, CompMeeseeksMemory memory, SavedJob savedJob, SavedTargetInfo jobTarget, ref JobAvailability jobAvailabilty)
        {
            Bill_Production bill = jobTarget.bill as Bill_Production;
            Job             job  = null;

            Logger.MessageFormat(this, "Checking for production bill job...");

            if (bill.repeatMode == BillRepeatModeDefOf.RepeatCount && bill.repeatCount < 1)
            {
                bill.deleted   = true;
                jobAvailabilty = JobAvailability.Complete;
                return(null);
            }
            else if (bill.repeatMode == BillRepeatModeDefOf.TargetCount)
            {
                // Might be here without a billgiver (after a save?) so try to set the current target
                if (jobTarget.Thing != null)
                {
                    bill.billStack.billGiver = jobTarget.Thing as IBillGiver;
                }

                // Otherwise count them later I guess :P
                if (bill.Map != null)
                {
                    int productCount = bill.recipe.WorkerCounter.CountProducts(bill);
                    if (productCount >= bill.targetCount)
                    {
                        bill.deleted   = true;
                        jobAvailabilty = JobAvailability.Complete;
                        return(null);
                    }
                }
            }

            Logger.MessageFormat(this, "Checking workstations...");

            bool workStationValid = (jobTarget.HasThing && !jobTarget.ThingDestroyed &&
                                     meeseeks.CanReserve(jobTarget.Thing, 1, -1, null, false) &&
                                     ((jobTarget.Thing as IBillGiver).CurrentlyUsableForBills() || (jobTarget.Thing as IBillGiver).UsableForBillsAfterFueling()));

            if (!workStationValid)
            {
                Logger.MessageFormat(this, "We think the workstation is invalid looking for new one");
                List <Building> buildings = meeseeks.MapHeld.listerBuildings.allBuildingsColonist.Where(building => building is IBillGiver &&
                                                                                                        savedJob.workGiverDef.fixedBillGiverDefs.Contains(building.def) &&
                                                                                                        meeseeks.CanReserve(building, 1, -1, null, false) &&
                                                                                                        ((building as IBillGiver).CurrentlyUsableForBills() || (building as IBillGiver).UsableForBillsAfterFueling())).ToList();

                if (buildings.Count > 0)
                {
                    Logger.MessageFormat(this, "Found new one");

                    buildings.Sort((a, b) => (int)(meeseeks.PositionHeld.DistanceTo(a.Position) - meeseeks.PositionHeld.DistanceTo(b.Position)));
                    jobTarget.target = buildings[0];
                    workStationValid = true;
                }
                else
                {
                    Logger.MessageFormat(this, "Found no alternate workstations...");
                }
            }
            else
            {
                Logger.MessageFormat(this, "We think the workstation is valid...");
            }

            if (workStationValid)
            {
                IBillGiver billGiver = jobTarget.Thing as IBillGiver;
                bill.billStack.billGiver = billGiver;

                Bill_ProductionWithUft bill_ProductionWithUft = bill as Bill_ProductionWithUft;
                if (bill_ProductionWithUft != null)
                {
                    if (bill_ProductionWithUft.BoundUft != null)
                    {
                        if (bill_ProductionWithUft.BoundUft.Creator.kindDef == MeeseeksDefOf.MeeseeksKind && meeseeks.CanReserveAndReach(bill_ProductionWithUft.BoundUft, PathEndMode.Touch, Danger.Deadly))
                        {
                            job = FinishUftJob(meeseeks, bill_ProductionWithUft.BoundUft, bill_ProductionWithUft, billGiver);
                        }
                    }
                    else
                    {
                        Predicate <Thing> validator       = (Thing t) => ((UnfinishedThing)t).Recipe == bill.recipe && ((UnfinishedThing)t).Creator.kindDef == MeeseeksDefOf.MeeseeksKind && ((UnfinishedThing)t).ingredients.TrueForAll((Thing x) => bill.IsFixedOrAllowedIngredient(x.def)) && meeseeks.CanReserve(t);
                        UnfinishedThing   unfinishedThing = (UnfinishedThing)GenClosest.ClosestThingReachable(meeseeks.Position, meeseeks.Map, ThingRequest.ForDef(bill.recipe.unfinishedThingDef), PathEndMode.InteractionCell, TraverseParms.For(meeseeks), 9999f, validator);
                        if (unfinishedThing != null)
                        {
                            job = FinishUftJob(meeseeks, unfinishedThing, bill_ProductionWithUft, billGiver);
                        }
                    }
                }

                if (job == null)
                {
                    List <ThingCount> chosenIngredients = new List <ThingCount>();
                    // Screw you I need this function
                    bool result = (bool)typeof(WorkGiver_DoBill).GetMethod("TryFindBestBillIngredients", BindingFlags.NonPublic | BindingFlags.Static).Invoke(null, new object[] { bill, meeseeks, jobTarget.Thing, chosenIngredients });

                    if (result)
                    {
                        Job haulOffJob = null;
                        job = WorkGiver_DoBill.TryStartNewDoBillJob(meeseeks, bill, billGiver, chosenIngredients, out haulOffJob);
                    }
                }
            }

            if (job == null)
            {
                jobAvailabilty = JobAvailability.Delayed;
            }
            else
            {
                jobAvailabilty = JobAvailability.Available;
            }

            return(job);
        }
示例#30
0
        private static bool setup(IntVec3 s, LocalTargetInfo dest, TraverseParms traverseParms, PathEndMode peMode, Map map)
        {
            sMap  = map;
            sMapW = map.Size.x;
            sMapH = map.Size.z;

            if (s.x < 0 || s.y < 0 || s.z < 0 || s.x >= sMapW || s.z >= sMapH)
            {
#if DEBUG_LOG_ERROR
                Log.Error("Start point is out side of map:" + s);
#endif
                return(true);
            }
            IntVec3 e = dest.Cell;
            if (e.x < 0 || e.y < 0 || e.z < 0 || e.x >= sMapW || e.z >= sMapH)
            {
#if DEBUG_LOG_ERROR
                Log.Error("End point is out side of map:" + e);
#endif
                return(true);
            }

            if (dest.HasThing && dest.Thing.Map != map)
            {
#if DEBUG_LOG_ERROR
                Log.Error("Tartget thing is not this map:" + dest.Thing.ThingID);
#endif
                return(true);
            }

            int w = (sMapW + NodeSetBitMask) >> NodeSetBitShift;
            sMapW4 = w;
            int h       = (sMapH + NodeSetBitMask) >> NodeSetBitShift;
            int wh_size = w * h;
            if (sNodeSet == null || sNodeSet.Length < wh_size)
            {
                sNodeSet = new NodeSet[wh_size];
            }

            sEndX = dest.Cell.x;
            sEndY = dest.Cell.z;

            sPathGrid      = sMap.pathGrid;
            sPathGridArray = sMap.pathGrid.pathGrid;
            sEdifice       = sMap.edificeGrid.InnerArray;
            sTopGrid       = sMap.terrainGrid.topGrid;
            sBlueprint     = sMap.blueprintGrid.InnerArray;

            sTraverseParms = traverseParms;
            Pawn pawn = traverseParms.pawn;
            if (pawn != null)
            {
                if (!pawn.Spawned || pawn.Map != map)
                {
#if DEBUG_LOG_ERROR
                    Log.Error("Pawn is not spawned or diff map");
#endif
                    return(true);
                }

                sCardinal               = pawn.TicksPerMoveCardinal;
                sDiagonal               = pawn.TicksPerMoveDiagonal;
                sAvoidGrid              = pawn.GetAvoidGrid(true);
                sAllowedArea            = allowedArea(pawn);
                sDrafted                = pawn.Drafted;
                sShouldCollideWithPawns = PawnUtility.ShouldCollideWithPawns(pawn);
            }
            else
            {
                sCardinal               = DefaultMoveTicksCardinal;
                sDiagonal               = DefaultMoveTicksDiagonal;
                sAvoidGrid              = null;
                sAllowedArea            = null;
                sDrafted                = false;
                sShouldCollideWithPawns = false;
            }
            sD2C = sDiagonal - (2 * sCardinal);

            sAllowWater =
                traverseParms.mode != TraverseMode.NoPassClosedDoorsOrWater &&
                traverseParms.mode != TraverseMode.PassAllDestroyableThingsNotWater;
            sPassAllDestroyableThings =
                traverseParms.mode == TraverseMode.PassAllDestroyableThings ||
                traverseParms.mode == TraverseMode.PassAllDestroyableThingsNotWater;

            setupDestRect(dest, traverseParms, peMode, sMap);

            return(false);
        }
示例#31
0
 public static bool TryFindGoodKidnapVictim(Pawn kidnapper, float maxDist, out Pawn victim, List <Thing> disallowed = null)
 {
     if (kidnapper.health.capacities.CapableOf(PawnCapacityDefOf.Manipulation) && kidnapper.Map.reachability.CanReachMapEdge(kidnapper.Position, TraverseParms.For(kidnapper, Danger.Some, TraverseMode.ByPawn, false)))
     {
         Predicate <Thing> validator = delegate(Thing t)
         {
             Pawn pawn = t as Pawn;
             if (!pawn.RaceProps.Humanlike)
             {
                 return(false);
             }
             if (!pawn.Downed)
             {
                 return(false);
             }
             if (pawn.Faction != Faction.OfPlayer)
             {
                 return(false);
             }
             if (!pawn.Faction.HostileTo(kidnapper.Faction))
             {
                 return(false);
             }
             if (!kidnapper.CanReserve(pawn, 1, -1, null, false))
             {
                 return(false);
             }
             if (disallowed != null && disallowed.Contains(pawn))
             {
                 return(false);
             }
             return(true);
         };
         victim = (Pawn)GenClosest.ClosestThingReachable(kidnapper.Position, kidnapper.Map, ThingRequest.ForGroup(ThingRequestGroup.Pawn), PathEndMode.OnCell, TraverseParms.For(TraverseMode.NoPassClosedDoors, Danger.Some, false), maxDist, validator, null, 0, -1, false, RegionType.Set_Passable, false);
         return(victim != null);
     }
     victim = null;
     return(false);
 }
示例#32
0
        public static bool TryIssueJobPackage(JobGiver_Work __instance, ref ThinkResult __result, Pawn pawn, JobIssueParams jobParams)
        {
#if DEBUG
            DateTime startTime = DateTime.Now;
#endif
            if (__instance.emergency && pawn.mindState.priorityWork.IsPrioritized)
            {
                List <WorkGiverDef> workGiversByPriority = pawn.mindState.priorityWork.WorkGiver.workType.workGiversByPriority;
                for (int i = 0; i < workGiversByPriority.Count; i++)
                {
                    WorkGiver worker = workGiversByPriority[i].Worker;
                    if (__instance.WorkGiversRelated(pawn.mindState.priorityWork.WorkGiver, worker.def))
                    {
                        Job job = GiverTryGiveJobPrioritized(__instance, pawn, worker, pawn.mindState.priorityWork.Cell);
                        if (job != null)
                        {
                            job.playerForced = true;
                            __result         = new ThinkResult(job, __instance, workGiversByPriority[i].tagToGive);
                            return(false);
                        }
                    }
                }
                pawn.mindState.priorityWork.Clear();
            }
            List <WorkGiver> list = (!__instance.emergency) ? pawn.workSettings.WorkGiversInOrderNormal : pawn.workSettings.WorkGiversInOrderEmergency;
            int               num = -999;
            TargetInfo        bestTargetOfLastPriority = TargetInfo.Invalid;
            WorkGiver_Scanner scannerWhoProvidedTarget = null;
            WorkGiver_Scanner scanner;
            IntVec3           pawnPosition;
            float             closestDistSquared;
            float             bestPriority;
            bool              prioritized;
            bool              allowUnreachable;
            Danger            maxPathDanger;
            for (int j = 0; j < list.Count; j++)
            {
                WorkGiver workGiver = list[j];
                if (workGiver.def.priorityInType != num && bestTargetOfLastPriority.IsValid)
                {
                    break;
                }
                if (!__instance.PawnCanUseWorkGiver(pawn, workGiver))
                {
                    continue;
                }
                try
                {
                    Job job2 = workGiver.NonScanJob(pawn);
                    if (job2 != null)
                    {
                        __result = new ThinkResult(job2, __instance, workGiver.def.tagToGive);
                        return(false);
                    }
                    scanner = (workGiver as WorkGiver_Scanner);

                    if (scanner != null)
                    {
                        if (scanner.def.scanThings)
                        {
//----------------------THERE HAVE BEEN NO CHANGES ABOVE THIS---------------------------------

                            Predicate <Thing> validator;
                            if (scanner is WorkGiver_DoBill workGiver_DoBill)
                            {
                                validator = (Thing t) => !t.IsForbidden(pawn) && WorkGiver_Scanner_Patch.HasJobOnThing(workGiver_DoBill, pawn, t);
                            }
                            else
                            {
                                validator = (Thing t) => !t.IsForbidden(pawn) && scanner.HasJobOnThing(pawn, t);
                            }
                            IEnumerable <Thing> enumerable = scanner.PotentialWorkThingsGlobal(pawn);
                            Thing thing;
                            if (scanner.Prioritized)
                            {
                                IEnumerable <Thing> enumerable2 = enumerable;
                                if (enumerable2 == null)
                                {
                                    enumerable2 = pawn.Map.listerThings.ThingsMatching(scanner.PotentialWorkThingRequest);
                                }
                                thing = ((!scanner.AllowUnreachable) ?
                                         GenClosest.ClosestThing_Global_Reachable(pawn.Position, pawn.Map, enumerable2, scanner.PathEndMode, TraverseParms.For(pawn, scanner.MaxPathDanger(pawn)), 9999f, validator, (Thing x) => scanner.GetPriority(pawn, x)) :
                                         GenClosest.ClosestThing_Global(pawn.Position, enumerable2, 99999f, validator, (Thing x) => scanner.GetPriority(pawn, x)));
                            }
                            else if (scanner.AllowUnreachable)
                            {
                                IEnumerable <Thing> enumerable3 = enumerable;
                                if (enumerable3 == null)
                                {
                                    enumerable3 = pawn.Map.listerThings.ThingsMatching(scanner.PotentialWorkThingRequest);
                                }
                                thing = GenClosest.ClosestThing_Global(pawn.Position, enumerable3, 99999f, validator);
                            }
                            else
                            {
                                //TODO: use better ThingRequest groups
                                if (
                                    workGiver.def.defName.Equals("DoctorFeedAnimals") ||
                                    workGiver.def.defName.Equals("DoctorFeedHumanlikes") ||
                                    workGiver.def.defName.Equals("DoctorTendToAnimals") ||
                                    workGiver.def.defName.Equals("DoctorTendToHumanlikes") ||
                                    workGiver.def.defName.Equals("DoBillsUseCraftingSpot") ||
                                    workGiver.def.defName.Equals("DoctorTendEmergency") ||
                                    workGiver.def.defName.Equals("HaulCorpses") ||
                                    workGiver.def.defName.Equals("FillFermentingBarrel") ||
                                    workGiver.def.defName.Equals("HandlingFeedPatientAnimals") ||
                                    workGiver.def.defName.Equals("Train") ||
                                    workGiver.def.defName.Equals("VisitSickPawn") ||
                                    workGiver.def.defName.Equals("DoBillsButcherFlesh") ||
                                    workGiver.def.defName.Equals("DoBillsCook") ||
                                    workGiver.def.defName.Equals("DoBillsMakeApparel")
                                    )
                                {
                                    //long
                                    thing = GenClosest_Patch.ClosestThingReachable2(pawn.Position, pawn.Map, scanner.PotentialWorkThingRequest, scanner.PathEndMode, TraverseParms.For(pawn, scanner.MaxPathDanger(pawn)), 9999f, validator, enumerable, 0, scanner.MaxRegionsToScanBeforeGlobalSearch, enumerable != null);
                                }
                                else if (
                                    workGiver.def.defName.Equals("HaulGeneral")
                                    )
                                {
                                    //long
                                    thing = HaulingCache.ClosestThingReachable(pawn, scanner, pawn.Map, scanner.PotentialWorkThingRequest, scanner.PathEndMode, TraverseParms.For(pawn, scanner.MaxPathDanger(pawn)), 9999f, validator, enumerable, 0, scanner.MaxRegionsToScanBeforeGlobalSearch, enumerable != null);
                                }

                                /*
                                 * else if(
                                 *              workGiver.def.defName.Equals("DoBillsButcherFlesh") ||
                                 *              workGiver.def.defName.Equals("DoBillsCook") ||
                                 *              workGiver.def.defName.Equals("DoBillsMakeApparel"))
                                 * {
                                 *
                                 *      thing = null;
                                 *      //ThingGrid_Patch
                                 *      int mapSizeX = pawn.Map.Size.x;
                                 *      int mapSizeZ = pawn.Map.Size.z;
                                 *      int index = pawn.Map.cellIndices.CellToIndex(pawn.Position);
                                 *      //Dictionary<Bill, float> billPointsDict = ThingGrid_Patch.thingBillPoints[t.def];
                                 *      Dictionary<WorkGiver_Scanner, Dictionary<float, List<HashSet<Thing>[]>>> ingredientDict = ThingGrid_Patch.mapIngredientDict[pawn.Map];
                                 *      ThingRequest thingReq = scanner.PotentialWorkThingRequest;
                                 *      if(!ingredientDict.TryGetValue(scanner, out Dictionary<float, List<HashSet<Thing>[]>> scoreToJumboCellsList)) {
                                 *              scoreToJumboCellsList = new Dictionary<float, List<HashSet<Thing>[]>>();
                                 *              List<Thing> thingsMatchingRequest = pawn.Map.listerThings.ThingsMatching(thingReq);
                                 *      }
                                 *
                                 * }
                                 */
                                else
                                {
                                    //long
                                    thing = GenClosest.ClosestThingReachable(pawn.Position, pawn.Map, scanner.PotentialWorkThingRequest, scanner.PathEndMode, TraverseParms.For(pawn, scanner.MaxPathDanger(pawn)), 9999f, validator, enumerable, 0, scanner.MaxRegionsToScanBeforeGlobalSearch, enumerable != null);
                                }
                            }
                            if (thing != null)
                            {
                                bestTargetOfLastPriority = thing;
                                scannerWhoProvidedTarget = scanner;
                            }
                        }
                        if (scanner.def.scanCells)
                        {
                            pawnPosition       = pawn.Position;
                            closestDistSquared = 99999f;
                            bestPriority       = float.MinValue;
                            prioritized        = scanner.Prioritized;
                            allowUnreachable   = scanner.AllowUnreachable;
                            maxPathDanger      = scanner.MaxPathDanger(pawn);
                            IEnumerable <IntVec3> enumerable4;
                            if (scanner is WorkGiver_GrowerSow workGiver_Grower)
                            {
                                //RimThreaded.WorkGiver_GrowerSow_Patch_JobOnCell = 0;

                                //thing = HaulingCache.ClosestThingReachable(pawn, scanner, pawn.Map, scanner.PotentialWorkThingRequest, scanner.PathEndMode, TraverseParms.For(pawn, scanner.MaxPathDanger(pawn)), 9999f, validator, enumerable, 0, scanner.MaxRegionsToScanBeforeGlobalSearch, enumerable != null);
                                IntVec3 bestCell = WorkGiver_Grower_Patch.ClosestLocationReachable(workGiver_Grower, pawn);
                                //Log.Message(bestCell.ToString());
                                if (bestCell.IsValid)
                                {
                                    bestTargetOfLastPriority = new TargetInfo(bestCell, pawn.Map);
                                    scannerWhoProvidedTarget = scanner;
                                }
                                //Log.Message(RimThreaded.WorkGiver_GrowerSow_Patch_JobOnCell.ToString());
                            }
                            else if (scanner is WorkGiver_GrowerHarvest workGiver_GrowerHarvest)
                            {
                                IntVec3 bestCell = WorkGiver_GrowerHarvest_Patch.ClosestLocationReachable(workGiver_GrowerHarvest, pawn);
                                if (bestCell.IsValid)
                                {
                                    bestTargetOfLastPriority = new TargetInfo(bestCell, pawn.Map);
                                    scannerWhoProvidedTarget = scanner;
                                }

                                /*
                                 * enumerable4 = workGiver_GrowerHarvest.PotentialWorkCellsGlobal(pawn);
                                 * IList<IntVec3> list2;
                                 * if ((list2 = (enumerable4 as IList<IntVec3>)) != null)
                                 * {
                                 *      for (int k = 0; k < list2.Count; k++)
                                 *      {
                                 *              ProcessCell(list2[k]);
                                 *      }
                                 * }
                                 * else
                                 * {
                                 *      foreach (IntVec3 item in enumerable4)
                                 *      {
                                 *              ProcessCell(item);
                                 *      }
                                 * }
                                 */
                            }
                            else
                            {
                                enumerable4 = scanner.PotentialWorkCellsGlobal(pawn);
                                IList <IntVec3> list2;
                                if ((list2 = (enumerable4 as IList <IntVec3>)) != null)
                                {
                                    for (int k = 0; k < list2.Count; k++)
                                    {
                                        ProcessCell(list2[k]);
                                    }
                                }
                                else
                                {
                                    foreach (IntVec3 item in enumerable4)
                                    {
                                        ProcessCell(item);
                                    }
                                }
                            }
                        }
                    }
                    void ProcessCell(IntVec3 c)
                    {
                        float newDistanceSquared = (c - pawnPosition).LengthHorizontalSquared;
                        float newPriority        = 0f;

                        if (prioritized)
                        {
                            newPriority = scanner.GetPriority(pawn, c);
                            if (newPriority < bestPriority)
                            {
                                return;
                            }
                        }

                        if (newDistanceSquared < closestDistSquared && !c.IsForbidden(pawn) && scanner.HasJobOnCell(pawn, c))
                        {
                            if (!allowUnreachable && !pawn.CanReach(c, scanner.PathEndMode, maxPathDanger))
                            {
                                return;
                            }

                            bestTargetOfLastPriority = new TargetInfo(c, pawn.Map);
                            scannerWhoProvidedTarget = scanner;
                            closestDistSquared       = newDistanceSquared;
                            bestPriority             = newPriority;
                        }
                    }
                }
                catch (Exception ex)
                {
                    Log.Error(string.Concat(pawn, " threw exception in WorkGiver ", workGiver.def.defName, ": ", ex.ToString()));
                }
                finally
                {
                }
                if (bestTargetOfLastPriority.IsValid)
                {
                    Job job3 = (!bestTargetOfLastPriority.HasThing) ? scannerWhoProvidedTarget.JobOnCell(pawn, bestTargetOfLastPriority.Cell) : scannerWhoProvidedTarget.JobOnThing(pawn, bestTargetOfLastPriority.Thing);
                    if (job3 != null)
                    {
                        job3.workGiverDef = scannerWhoProvidedTarget.def;
                        __result          = new ThinkResult(job3, __instance, list[j].def.tagToGive);
                        return(false);
                    }

                    //If this was a cached plant job, deregister it
                    if (scannerWhoProvidedTarget is WorkGiver_GrowerSow)
                    {
                        Map          map       = pawn.Map;
                        IntVec3      cell      = bestTargetOfLastPriority.Cell;
                        List <Thing> thingList = cell.GetThingList(map);
                        foreach (Thing thing in thingList)
                        {
                            if (thing is Building_PlantGrower buildingPlantGrower)
                            {
                                PlantSowing_Cache.ReregisterObject(map, cell,
                                                                   WorkGiver_Grower_Patch.awaitingPlantCellsMapDict);
                            }
                        }
                        PlantSowing_Cache.ReregisterObject(map, cell, WorkGiver_Grower_Patch.awaitingPlantCellsMapDict);
                    }
                    //HACK - I know. I'm awful.
                    //Log.ErrorOnce(string.Concat(scannerWhoProvidedTarget, " provided target ", bestTargetOfLastPriority, " but yielded no actual job for pawn ", pawn, ". The CanGiveJob and JobOnX methods may not be synchronized."), 6112651);
                    Log.Warning(string.Concat(scannerWhoProvidedTarget, " provided target ", bestTargetOfLastPriority, " but yielded no actual job for pawn ", pawn, ". The CanGiveJob and JobOnX methods may not be synchronized."));
                }
                num = workGiver.def.priorityInType;

#if DEBUG
                int milli99 = (int)DateTime.Now.Subtract(startTime).TotalMilliseconds;
                if (milli99 > 300)
                {
                    Log.Warning("99 JobGiver_Work.TryIssueJobPackage Took over " + milli99.ToString() + "ms for workGiver: " + workGiver.def.defName);
                    //Log.Warning(scanner.PotentialWorkThingRequest.ToString());
                    //Log.Warning(validator.ToString());
                }
#endif
            }
            __result = ThinkResult.NoJob;
            return(false);
        }
        public override void ProcessInput(Event ev)
        {
            base.ProcessInput(ev);
            if (this.transporters == null)
            {
                this.transporters = new List <CompTransporter>();
            }
            if (!this.transporters.Contains(this.transComp))
            {
                this.transporters.Add(this.transComp);
            }
            CompLaunchable launchable = this.transComp.Launchable;

            if (launchable != null)
            {
                Building fuelingPortSource = launchable.FuelingPortSource;
                if (fuelingPortSource != null)
                {
                    Map map = this.transComp.Map;
                    Command_LoadToTransporter.tmpFuelingPortGivers.Clear();
                    map.floodFiller.FloodFill(fuelingPortSource.Position, (IntVec3 x) => FuelingPortUtility.AnyFuelingPortGiverAt(x, map), delegate(IntVec3 x)
                    {
                        Command_LoadToTransporter.tmpFuelingPortGivers.Add(FuelingPortUtility.FuelingPortGiverAt(x, map));
                    }, 2147483647, false, null);
                    for (int i = 0; i < this.transporters.Count; i++)
                    {
                        Building fuelingPortSource2 = this.transporters[i].Launchable.FuelingPortSource;
                        if (fuelingPortSource2 != null && !Command_LoadToTransporter.tmpFuelingPortGivers.Contains(fuelingPortSource2))
                        {
                            Messages.Message("MessageTransportersNotAdjacent".Translate(), fuelingPortSource2, MessageTypeDefOf.RejectInput);
                            return;
                        }
                    }
                }
            }
            for (int j = 0; j < this.transporters.Count; j++)
            {
                if (this.transporters[j] != this.transComp && !this.transComp.Map.reachability.CanReach(this.transComp.parent.Position, this.transporters[j].parent, PathEndMode.Touch, TraverseParms.For(TraverseMode.PassDoors, Danger.Deadly, false)))
                {
                    Messages.Message("MessageTransporterUnreachable".Translate(), this.transporters[j].parent, MessageTypeDefOf.RejectInput);
                    return;
                }
            }
            Find.WindowStack.Add(new Dialog_LoadTransporters(this.transComp.Map, this.transporters));
        }
        //FindPath parameter validation
        private bool ValidateFindPathParameters(Pawn pawn, IntVec3 start, LocalTargetInfo dest, TraverseParms traverseParms, PathEndMode peMode, bool canPassAnything)
        {
            if (pawn != null && pawn.Map != this.map)
            {
                Log.Error(string.Concat("Tried to FindPath for pawn which is spawned in another map. His map PathFinder should have been used, not this one. pawn=", pawn, " pawn.Map=", pawn.Map, " map=", this.map));
                return(false);
            }

            if (!start.IsValid)
            {
                Log.Error(string.Concat("Tried to FindPath with invalid start ", start, ", pawn= ", pawn));
                return(false);
            }
            if (!dest.IsValid)
            {
                Log.Error(string.Concat("Tried to FindPath with invalid dest ", dest, ", pawn= ", pawn));
                return(false);
            }

            if (!canPassAnything)
            {
                //For offline testing, reachability check can crash with null pawn
                if (Current.ProgramState == ProgramState.Playing)
                {
                    if (!this.map.reachability.CanReach(start, dest, peMode, traverseParms))
                    {
                        return(false);
                    }
                }
                map.regionAndRoomUpdater.RebuildDirtyRegionsAndRooms();
            }
            else if (dest.HasThing && dest.Thing.Map != this.map)
            {
                return(false);
            }
            return(true);
        }
示例#35
0
        public void TryRevive(bool ForcedRevive = false)
        {
            string str = "sucessful";

            reviveIntervalTicks = -1;
            reviveTried         = true;
            Rand.PushState();
            if (Rand.Chance(reanimateChance) || ForcedRevive)
            {
                List <Hediff> hediffs = unhealableHediffs;
                ResurrectionUtility.Resurrect(pawn);
                if (originalWeapon == null && pawn.kindDef.weaponTags.Count > 0)
                {
                    ThingDef thingDef = ThingDef.Named(pawn.kindDef.weaponTags[0]);
                    Thing    thing2   = GenClosest.ClosestThingReachable(pawn.Position, pawn.Map, ThingRequest.ForDef(thingDef), PathEndMode.InteractionCell, TraverseParms.For(pawn, Danger.Deadly, TraverseMode.ByPawn, false));
                    this.originalWeapon = (ThingWithComps)thing2;
                }
                if (originalWeapon != null)
                {
                    ThingWithComps thing = originalWeapon;
                    if (thing.Spawned)
                    {
                        thing.DeSpawn();
                    }
                    if (pawn.inventory.innerContainer.Contains(thing))
                    {
                        pawn.inventory.innerContainer.Remove(thing);
                    }
                    pawn.equipment.AddEquipment(thing);
                }
                if (secondryWeapon != null)
                {
                    ThingWithComps thing = secondryWeapon;
                    if (thing.Spawned)
                    {
                        thing.DeSpawn();
                    }
                    if (pawn.inventory.innerContainer.Contains(thing))
                    {
                        pawn.inventory.innerContainer.Remove(thing);
                    }
                    //    pawn.equipment.AdMechAddOffHandEquipment(thing);
                }
                if (!ForcedRevive)
                {
                    bool revives = true;
                    foreach (Hediff item in hediffs)
                    {
                        if (!pawn.health.hediffSet.PartIsMissing(item.Part))
                        {
                            if (pawn.health.WouldDieAfterAddingHediff(item))
                            {
                                revives = false;
                                str     = "failiure";
                            }
                            if (pawn.health.WouldBeDownedAfterAddingHediff(item))
                            {
                                revives = false;
                                str     = "failiure: still downed";
                            }
                            pawn.health.AddHediff(item);
                        }
                    }
                }
                ThrowNecronGlow(pos.ToVector3(), map, 5f);
                MoteMaker.MakeStaticMote(pos, map, ThingDefOf.Mote_ExplosionFlash, 3f);
                //    log.message(string.Format("{0} revive {1}",pawn, str));
            }
            else
            {
                str = "failiure: roll";
                //    log.message(string.Format("{0} revive {1}", pawn, str));
            }
            Rand.PopState();
        }
        protected override Job TryGiveJob(Pawn pawn)
        {
            if (Find.TickManager.TicksGame < PrevTick + 10)
            {
                return(null);
            }
            PrevTick = Find.TickManager.TicksGame;
            if (GridsUtility.Fogged(pawn.Position, pawn.Map))
            {
                return(JobMaker.MakeJob(JobDefOf.LayDown));
            }

            Alien alien = pawn as Alien;

            // Some optimizations here...
            //if (pawn.TryGetAttackVerb(null, false) == null)
            //{
            //    return null;
            //}
            if (pawn.CurJob != null)
            {
                Log.Message(pawn + " - " + pawn.CurJob.def.defName);
            }
            Pawn pawn2 = null;

            if ((Find.TickManager.TicksGame - alien.lastAttacked) < 1000)
            {
                pawn2 = alien.lastInstigator;
            }
            else if ((Find.TickManager.TicksGame - pawn.Map.GetComponent <MapComponent_MapEvents>().LastAttacked) < 1000)
            {
                pawn2 = FindPawnTargetNearPlants(pawn);
            }
            else
            {
                pawn2 = FindPawnTarget(pawn);
            }
            if (pawn2 == null)
            {
                if (pawn.GetRoom() != null && !pawn.GetRoom().PsychologicallyOutdoors)
                {
                    Predicate <Thing> validator = delegate(Thing t)
                    {
                        return(t.def.defName.ToLower().Contains("door"));
                    };
                    var door = GenClosest.ClosestThingReachable(pawn.Position,
                                                                pawn.Map, ThingRequest.ForGroup(ThingRequestGroup.BuildingArtificial), PathEndMode.Touch, TraverseParms.For(pawn, Danger.Deadly,
                                                                                                                                                                            TraverseMode.ByPawn, false)
                                                                , 5f, validator);
                    if (door != null)
                    {
                        return(PurpleIvyUtils.MeleeAttackJob(pawn, door));
                    }
                    else
                    {
                        Predicate <Thing> validator2 = delegate(Thing t)
                        {
                            return(t.def.defName.ToLower().Contains("wall"));
                        };
                        var wall = GenClosest.ClosestThingReachable(pawn.Position,
                                                                    pawn.Map, ThingRequest.ForGroup(ThingRequestGroup.BuildingArtificial), PathEndMode.Touch, TraverseParms.For(pawn, Danger.Deadly,
                                                                                                                                                                                TraverseMode.ByPawn, false)
                                                                    , 5f, validator2);
                        if (wall != null)
                        {
                            return(PurpleIvyUtils.MeleeAttackJob(pawn, wall));
                        }
                    }
                }
            }
            else if (!pawn2.Downed)
            {
                var verb = pawn.VerbTracker.AllVerbs.Where(x => x.IsMeleeAttack != true).FirstOrDefault();
                if (pawn.def == PurpleIvyDefOf.Genny_ParasiteOmega && pawn.Position.InHorDistOf(pawn2.Position, 15) && Rand.Chance(0.7f))
                {
                    //Log.Message(Find.TickManager.TicksGame.ToString() + " - " + pawn + " - " + pawn.jobs?.curJob?.def?.defName + " - JUMP");
                    return(PurpleIvyUtils.JumpOnTargetJob(pawn, pawn2));
                }
                else if (pawn.def == PurpleIvyDefOf.Genny_ParasiteBeta && pawn.Position.InHorDistOf(pawn2.Position, 2) && Rand.Chance(0.1f))
                {
                    //Log.Message(Find.TickManager.TicksGame.ToString() + " - " + pawn + " - " + pawn.jobs?.curJob?.def?.defName + " - SMOKE");
                    return(PurpleIvyUtils.SmokeAttackJob(pawn, pawn2));
                }
                else if (verb != null && Rand.Chance(0.8f) && pawn.Position.InHorDistOf(pawn2.Position, verb.verbProps.range))
                {
                    //Log.Message(Find.TickManager.TicksGame.ToString() + " - " + pawn + " - " + pawn.jobs?.curJob?.def?.defName + " - SHOOT");
                    return(PurpleIvyUtils.RangeAttackJob(pawn, pawn2));
                }
                else
                {
                    //Log.Message(Find.TickManager.TicksGame.ToString() + " - " + pawn + " - " + pawn.jobs?.curJob?.def?.defName + " - MELEE");
                    return(PurpleIvyUtils.MeleeAttackJob(pawn, pawn2));
                }
            }
            else if (pawn2.Downed)
            {
                if (pawn2.BodySize >= 0.5f && pawn.def != PurpleIvyDefOf.Genny_ParasiteOmega &&
                    pawn.def != PurpleIvyDefOf.Genny_ParasiteGamma &&
                    pawn.kindDef != PurpleIvyDefOf.Genny_Queen &&
                    pawn.needs.food.CurCategory < HungerCategory.Hungry)
                {
                    //Log.Message(Find.TickManager.TicksGame.ToString() + " - " + pawn + " - " + pawn.jobs?.curJob?.def?.defName + " - Goo");
                    return(PurpleIvyUtils.EntagleWithGooJob(pawn, pawn2));
                }
                else
                {
                    //Log.Message(Find.TickManager.TicksGame.ToString() + " - " + pawn + " - " + pawn.jobs?.curJob?.def?.defName + " - KILL");
                    return(PurpleIvyUtils.KillAttackJob(pawn, pawn2));
                }
            }
            if (alien.canGuard)
            {
                if (alien.mindState?.duty?.focus == null || !PurpleIvyUtils.AlienPlantInCell
                        (alien.Map, alien.mindState.duty.focus.Cell))
                {
                    alien.SetFocus();
                }
            }
            if (alien.canHaul)
            {
                Predicate <Thing> validator = delegate(Thing t)
                {
                    List <Thing> list = pawn.Map.thingGrid.ThingsListAt(t.Position);
                    return(!(list.Count > 0 && list.OfType <Plant>().Any(x =>
                                                                         x.def == PurpleIvyDefOf.PurpleIvy || x.def == PurpleIvyDefOf.PI_Nest ||
                                                                         x.def == PurpleIvyDefOf.PlantVenomousToothwort)));
                };

                Thing thing = GenClosest.ClosestThingReachable(pawn.Position, pawn.Map,
                                                               ThingRequest.ForDef(PurpleIvyDefOf.PI_StickyGoo), PathEndMode.ClosestTouch,
                                                               TraverseParms.For(pawn, Danger.None, TraverseMode.NoPassClosedDoors, false), 9999f, validator, null);
                if (thing == null)
                {
                    thing = GenClosest.ClosestThingReachable(pawn.Position, pawn.Map,
                                                             ThingRequest.ForGroup(ThingRequestGroup.Corpse), PathEndMode.ClosestTouch,
                                                             TraverseParms.For(pawn, Danger.None, TraverseMode.NoPassClosedDoors, false), 50f, validator, null);
                }
                if (thing != null && ReservationUtility.CanReserveAndReach(pawn, thing, PathEndMode.ClosestTouch, Danger.None))
                {
                    var plants = pawn.Map.listerThings.ThingsOfDef(PurpleIvyDefOf.PurpleIvy);
                    if (plants == null || plants.Count <= 0)
                    {
                        return(null);
                    }
                    var plantToHaul = plants.RandomElement();
                    if (ReachabilityUtility.CanReach(pawn, plantToHaul, PathEndMode.ClosestTouch, Danger.None,
                                                     true, TraverseMode.NoPassClosedDoors))
                    {
                        Job job = JobMaker.MakeJob(PurpleIvyDefOf.PI_HaulToCell, thing, plantToHaul.Position);
                        job.attackDoorIfTargetLost = true;
                        if (job != null && job.TryMakePreToilReservations(pawn, false))
                        {
                            ReservationUtility.Reserve(pawn, thing, job);
                            return(job);
                        }
                    }
                }
            }

            //Log.Message(Find.TickManager.TicksGame.ToString() + " - " + pawn + " - " + pawn.jobs?.curJob?.def?.defName + " - NULL 1");
            //Building building = this.FindTurretTarget(pawn);
            //if (building != null)
            //{
            //    return MeleeAttackJob(pawn, building);
            //}
            //if (pawn2 != null)
            //{
            //    using (PawnPath pawnPath = pawn.Map.pathFinder.FindPath(pawn.Position, pawn2.Position, TraverseParms.For(pawn, Danger.Deadly, TraverseMode.PassDoors, false), PathEndMode.OnCell))
            //    {
            //        if (!pawnPath.Found)
            //        {
            //            return null;
            //        }
            //        IntVec3 loc;
            //        if (!pawnPath.TryFindLastCellBeforeBlockingDoor(pawn, out loc))
            //        {
            //            Log.Error(pawn + " did TryFindLastCellBeforeDoor but found none when it should have been one. Target: " + pawn2.LabelCap, false);
            //            return null;
            //        }
            //        IntVec3 randomCell = CellFinder.RandomRegionNear(loc.GetRegion(pawn.Map, RegionType.Set_Passable), 9, TraverseParms.For(pawn, Danger.Deadly, TraverseMode.ByPawn, false), null, null, RegionType.Set_Passable).RandomCell;
            //        if (randomCell == pawn.Position)
            //        {
            //            return JobMaker.MakeJob(JobDefOf.Wait, 30, false);
            //        }
            //        return JobMaker.MakeJob(JobDefOf.Goto, randomCell);
            //    }
            //}
            return(null);
        }