예제 #1
0
        public void Scan(List <Pawn> pawns, int range, int maxLinked)
        {
            rangeCache = range * range;
            IntVec3 parentPosition = owner.Position;

            linkedPawns.RemoveWhere(p => !p.Spawned || parentPosition.DistanceToSquared(p.Position) > rangeCache);

            if (linkedPawns.Count >= maxLinked)
            {
                return;
            }

            for (int i = 0; i < pawns.Count; i++)
            {
                Pawn            pawn = pawns[i];
                PawnLinkNetwork link = pawn.GetComp <CompPawnLink>()?.Link;

                if (link == null || network != link.network || owner == pawn)
                {
                    continue;
                }

                int maxRange = Math.Max(rangeCache, link.rangeCache);

                if (parentPosition.DistanceToSquared(pawn.Position) <= maxRange)
                {
                    if (linkedPawns.Add(pawn) && linkedPawns.Count >= maxLinked)
                    {
                        break;
                    }
                }
            }
        }
예제 #2
0
        private bool TryFindStartAndEndCells(Map map, out IntVec3 start, out IntVec3 end)
        {
            if (!RCellFinder.TryFindRandomPawnEntryCell(out start, map, CellFinder.EdgeRoadChance_Animal, (Predicate <IntVec3>)null))
            {
                end = IntVec3.Invalid;
                return(false);
            }
            end = IntVec3.Invalid;
            int num = 0;

            while (num < 8)
            {
                IntVec3 startLocal = start;
                IntVec3 intVec     = default(IntVec3);
                if (CellFinder.TryFindRandomEdgeCellWith((Predicate <IntVec3>)((IntVec3 x) => map.reachability.CanReach(startLocal, x, PathEndMode.OnCell, TraverseMode.NoPassClosedDoors, Danger.Deadly)), map, CellFinder.EdgeRoadChance_Ignore, out intVec))
                {
                    if (!end.IsValid || intVec.DistanceToSquared(start) > end.DistanceToSquared(start))
                    {
                        end = intVec;
                    }
                    num++;
                    continue;
                }
                break;
            }
            return(end.IsValid);
        }
예제 #3
0
        public static bool TryFindDirectFleeDestination(IntVec3 root, float dist, Pawn pawn, out IntVec3 result)
        {
            for (int i = 0; i < 30; i++)
            {
                result = root + IntVec3.FromVector3(Vector3Utility.HorizontalVectorFromAngle(Rand.Range(0, 360)) * dist);
                if (result.Walkable(pawn.Map) && result.DistanceToSquared(pawn.Position) < result.DistanceToSquared(root) && GenSight.LineOfSight(root, result, pawn.Map, skipFirstCell: true))
                {
                    return(true);
                }
            }
            Region region = pawn.GetRegion();

            for (int j = 0; j < 30; j++)
            {
                IntVec3 randomCell = CellFinder.RandomRegionNear(region, 15, TraverseParms.For(pawn)).RandomCell;
                if (randomCell.Walkable(pawn.Map) && (float)(root - randomCell).LengthHorizontalSquared > dist * dist)
                {
                    using (PawnPath path = pawn.Map.pathFinder.FindPath(pawn.Position, randomCell, pawn))
                    {
                        if (PawnPathUtility.TryFindCellAtIndex(path, (int)dist + 3, out result))
                        {
                            return(true);
                        }
                    }
                }
            }
            result = pawn.Position;
            return(false);
        }
        private bool TryFindStartAndEndCells(Map map, out IntVec3 start, out IntVec3 end)
        {
            bool result;

            if (!RCellFinder.TryFindRandomPawnEntryCell(out start, map, CellFinder.EdgeRoadChance_Animal, null))
            {
                end    = IntVec3.Invalid;
                result = false;
            }
            else
            {
                end = IntVec3.Invalid;
                for (int i = 0; i < 8; i++)
                {
                    IntVec3 startLocal = start;
                    IntVec3 intVec;
                    if (!CellFinder.TryFindRandomEdgeCellWith((IntVec3 x) => map.reachability.CanReach(startLocal, x, PathEndMode.OnCell, TraverseMode.NoPassClosedDoors, Danger.Deadly), map, CellFinder.EdgeRoadChance_Ignore, out intVec))
                    {
                        break;
                    }
                    if (!end.IsValid || intVec.DistanceToSquared(start) > end.DistanceToSquared(start))
                    {
                        end = intVec;
                    }
                }
                result = end.IsValid;
            }
            return(result);
        }
예제 #5
0
        private int GetDistanceSquaredToExistingEdgeThing(IntVec3 cell, CellRect rect, ThingDef thingDef)
        {
            Map map = BaseGen.globalSettings.map;
            int num = 2147483647;

            foreach (IntVec3 edgeCell in rect.EdgeCells)
            {
                List <Thing> thingList = edgeCell.GetThingList(map);
                bool         flag      = false;
                int          num2      = 0;
                while (num2 < thingList.Count)
                {
                    if (thingList[num2].def != thingDef)
                    {
                        num2++;
                        continue;
                    }
                    flag = true;
                    break;
                }
                if (flag)
                {
                    num = Mathf.Min(num, cell.DistanceToSquared(edgeCell));
                }
            }
            return(num);
        }
        public static bool TryFindDirectFleeDestination(IntVec3 root, float dist, Pawn pawn, out IntVec3 result)
        {
            for (int i = 0; i < 30; i++)
            {
                result = root + IntVec3.FromVector3(Vector3Utility.HorizontalVectorFromAngle((float)Rand.RangeSeeded(0, 360, Find.TickManager.TicksAbs + pawn.thingIDNumber)) * dist);
                if (result.Walkable(pawn.Map) && result.DistanceToSquared(pawn.Position) < result.DistanceToSquared(root) && GenSight.LineOfSight(root, result, pawn.Map, true, null, 0, 0))
                {
                    return(true);
                }
            }
            Region region = pawn.GetRegion(RegionType.Set_Passable);

            for (int j = 0; j < 30; j++)
            {
                Region  region2    = CellFinder.RandomRegionNear(region, 15, TraverseParms.For(pawn, Danger.Deadly, TraverseMode.ByPawn, false), null, null, RegionType.Set_Passable);
                IntVec3 randomCell = region2.RandomCell;
                if (randomCell.Walkable(pawn.Map) && (float)(root - randomCell).LengthHorizontalSquared > dist * dist)
                {
                    using (PawnPath pawnPath = pawn.Map.pathFinder.FindPath(pawn.Position, randomCell, pawn, PathEndMode.OnCell))
                    {
                        if (PawnPathUtility.TryFindCellAtIndex(pawnPath, (int)dist + 3, out result))
                        {
                            return(true);
                        }
                    }
                }
            }
            result = pawn.Position;
            return(false);
        }
        private bool TryFindHiveSpawnCell(Map map, out IntVec3 spawnCell)
        {
            float   num     = -1f;
            IntVec3 intVec  = IntVec3.Invalid;
            int     num2    = 0;
            IntVec3 intVec2 = default(IntVec3);

            while (num2 < 3 && (from x in this.possibleSpawnCells
                                where x.Standable(map) && x.GetFirstItem(map) == null && x.GetFirstBuilding(map) == null && x.GetFirstPawn(map) == null
                                select x).TryRandomElement <IntVec3>(out intVec2))
            {
                float num3 = -1f;
                for (int i = 0; i < this.spawnedHives.Count; i++)
                {
                    float num4 = (float)intVec2.DistanceToSquared(this.spawnedHives[i].Position);
                    if (num3 < 0.0 || num4 < num3)
                    {
                        num3 = num4;
                    }
                }
                if (!intVec.IsValid || num3 > num)
                {
                    intVec = intVec2;
                    num    = num3;
                }
                num2++;
            }
            spawnCell = intVec;
            return(spawnCell.IsValid);
        }
예제 #8
0
        public static bool CheckForCollisionCallback(ProjectileCE projectile, IntVec3 cell, Thing launcher)
        {
            /* Check if an active shield can block this projectile, we don't check if the projectile flies overhead, as those projectiles don't call this function
             */
            Map     map           = projectile.Map;
            Vector3 exactPosition = projectile.ExactPosition;
            IntVec3 origin        = projectile.OriginIV3;

            getShields(map);

            foreach (Building building in shields)
            {
                var  shield    = building as Building_Shield;
                var  generator = shield.GetComp <Comp_ShieldGenerator>();
                bool isActive  = generator.IsActive();
                if (!isActive)
                {
                    continue;
                }
                bool blockDirect = generator.BlockDirect_Active();
                if (!blockDirect)
                {
                    continue;
                }
                int   fieldRadius      = (int)generator.FieldRadius_Active();
                int   fieldRadiusSq    = fieldRadius * fieldRadius;
                float DistanceSq       = projectile.Position.DistanceToSquared(shield.Position) - fieldRadiusSq;
                float originDistanceSq = origin.DistanceToSquared(shield.Position) - fieldRadiusSq;
                if (DistanceSq > 0)
                {
                    continue;
                }
                if (originDistanceSq < 0)
                {
                    continue;
                }
                Vector3    shieldPosition2D = new Vector3(shield.Position.x, 0, shield.Position.z);
                Quaternion targetAngle      = projectile.ExactRotation;
                Quaternion shieldProjAng    = Quaternion.LookRotation(exactPosition - shieldPosition2D);
                if ((Quaternion.Angle(targetAngle, shieldProjAng) > 90))
                {
                    HitSoundDef.PlayOneShot((SoundInfo) new TargetInfo(shield.Position, map, false));


                    int damage = (projectile.def.projectile.GetDamageAmount(launcher));

                    generator.FieldIntegrity_Current -= damage;

                    exactPosition = getExactPosition(origin.ToVector3(), projectile.ExactPosition, shield.Position.ToVector3(), (fieldRadius - 1) * (fieldRadius - 1));
                    MoteMaker.ThrowLightningGlow(exactPosition, map, 0.5f);
                    projectile.ExactPosition = exactPosition;

                    return(true);
                }
            }
            return(false);
        }
예제 #9
0
        public static IntVec3 RandomWanderDestFor(Pawn pawn, IntVec3 root, float radius, Func <Pawn, IntVec3, bool> validator, Danger maxDanger)
        {
            if (radius > 12.0)
            {
                Log.Warning("wanderRadius of " + radius + " is greater than Region.GridSize of " + 12 + " and will break.");
            }
            bool flag = UnityData.isDebugBuild && DebugViewSettings.drawDestSearch;

            if (root.GetRegion(pawn.Map, RegionType.Set_Passable) != null)
            {
                int maxRegions = Mathf.Max((int)radius / 3, 13);
                CellFinder.AllRegionsNear(RCellFinder.regions, root.GetRegion(pawn.Map, RegionType.Set_Passable), maxRegions, TraverseParms.For(pawn, Danger.Deadly, TraverseMode.ByPawn, false), (Region reg) => reg.extentsClose.ClosestDistSquaredTo(root) <= radius * radius, null, RegionType.Set_Passable);
                if (flag)
                {
                    pawn.Map.debugDrawer.FlashCell(root, 0.6f, "root", 50);
                }
                if (RCellFinder.regions.Count > 0)
                {
                    for (int i = 0; i < 35; i++)
                    {
                        IntVec3 randomCell = RCellFinder.regions.RandomElementByWeight((Region reg) => (float)reg.CellCount).RandomCell;
                        if ((float)randomCell.DistanceToSquared(root) > radius * radius)
                        {
                            if (flag)
                            {
                                pawn.Map.debugDrawer.FlashCell(randomCell, 0.32f, "distance", 50);
                            }
                            continue;
                        }
                        if (!RCellFinder.CanWanderToCell(randomCell, pawn, root, validator, i, maxDanger))
                        {
                            if (flag)
                            {
                                pawn.Map.debugDrawer.FlashCell(randomCell, 0.6f, "validation", 50);
                            }
                            continue;
                        }
                        if (flag)
                        {
                            pawn.Map.debugDrawer.FlashCell(randomCell, 0.9f, "go!", 50);
                        }
                        return(randomCell);
                    }
                }
            }
            IntVec3 position = default(IntVec3);

            if (!CellFinder.TryFindRandomCellNear(root, pawn.Map, Mathf.FloorToInt(radius), (Predicate <IntVec3>)((IntVec3 c) => c.InBounds(pawn.Map) && pawn.CanReach(c, PathEndMode.OnCell, Danger.None, false, TraverseMode.ByPawn) && !c.IsForbidden(pawn)), out position) && !CellFinder.TryFindRandomCellNear(root, pawn.Map, Mathf.FloorToInt(radius), (Predicate <IntVec3>)((IntVec3 c) => c.InBounds(pawn.Map) && pawn.CanReach(c, PathEndMode.OnCell, Danger.Deadly, false, TraverseMode.ByPawn)), out position) && !CellFinder.TryFindRandomCellNear(root, pawn.Map, 20, (Predicate <IntVec3>)((IntVec3 c) => c.InBounds(pawn.Map) && pawn.CanReach(c, PathEndMode.OnCell, Danger.None, false, TraverseMode.ByPawn) && !c.IsForbidden(pawn)), out position) && !CellFinder.TryFindRandomCellNear(root, pawn.Map, 30, (Predicate <IntVec3>)((IntVec3 c) => c.InBounds(pawn.Map) && pawn.CanReach(c, PathEndMode.OnCell, Danger.Deadly, false, TraverseMode.ByPawn)), out position) && !CellFinder.TryFindRandomCellNear(pawn.Position, pawn.Map, 5, (Predicate <IntVec3>)((IntVec3 c) => c.InBounds(pawn.Map) && pawn.CanReach(c, PathEndMode.OnCell, Danger.Deadly, false, TraverseMode.ByPawn)), out position))
            {
                position = pawn.Position;
            }
            if (flag)
            {
                pawn.Map.debugDrawer.FlashCell(position, 0.4f, "fallback", 50);
            }
            return(position);
        }
        private List <Plant> GetValidForagingTargetsSorted()
        {
            IntVec3 position = manager.map.GetBaseCenter();

            return(manager.map.listerThings.AllThings
                   .Where(IsValidForagingTarget)

                   // OrderBy defaults to ascending, switch sign on current yield to get descending
                   .Select(p => p as Plant)
                   .OrderBy(p => - p.YieldNow() / (Math.Sqrt(position.DistanceToSquared(p.Position)) * 2))
                   .ToList());
        }
예제 #11
0
        public static IntVec3 BestCarnivalSetupPosition(IntVec3 initPos, Map map)
        {
            IntVec3 averageColPos;

            if (!(averageColPos = CellsUtil.ApproxClosestColonistBuilding(map, initPos, ThingDefOf.Door)).IsValid &&
                !(averageColPos = CellsUtil.ApproxClosestColonistBuilding(map, initPos, ThingDefOf.Wall)).IsValid)
            {
                averageColPos = AverageColPos;
            }
            else
            {
                averageColPos = averageColPos.AverageWith(AverageColPos);
            }

            var distSqrdToColony = initPos.DistanceToSquared(averageColPos);

            if (Prefs.DevMode)
            {
                Log.Message("[Carnivale] setupSpot: initPos=" + initPos + ", averageColPos=" + averageColPos + ", distSqrdToColony=" + distSqrdToColony);
            }

            var result = initPos;

            if (!TryCarnivalSetupPosition_Triangular(initPos, averageColPos, distSqrdToColony, map, out result))
            {
                if (Prefs.DevMode)
                {
                    Log.Warning("\t[Carnivale] setupSpot: triangular algorithm failed. Using old random iteration algorithm.");
                }

                TryCarnivalSetupPosition_Random(initPos, averageColPos, 7, map, out result);
            }

            if (Prefs.DevMode)
            {
                if (result == initPos)
                {
                    Log.Error(string.Concat(new object[]
                    {
                        "[Carnivale] Could not find carnival setup spot from ",
                        initPos,
                        ", expect more errors. Using ",
                        initPos
                    }));
                }

                Log.Message("[Carnivale] setupSpot: final pass: "******". distToColony=" + result.DistanceTo(averageColPos));

                map.debugDrawer.FlashCell(result, 0.5f, "Setup Spot");
            }

            return(result);
        }
예제 #12
0
        public static bool ProcessEquidistantCells(
            IntVec3 center,
            float radius,
            Func <List <IntVec3>, bool> processor,
            Map map = null)
        {
            //if (GenRadial.working)
            //{
            //Log.Error("Nested calls to ProcessEquidistantCells() are not allowed.", false);
            //}
            //else
            //{
            //GenRadial.tmpCells.Clear();
            List <IntVec3> tmpCells = new List <IntVec3>();

            //GenRadial.working = true;
            try
            {
                float num1 = -1f;
                int   num2 = GenRadial.NumCellsInRadius(radius);
                for (int index = 0; index < num2; ++index)
                {
                    IntVec3 intVec3 = center + GenRadial.RadialPattern[index];
                    if (map == null || intVec3.InBounds(map))
                    {
                        float squared = (float)intVec3.DistanceToSquared(center);
                        if ((double)Mathf.Abs(squared - num1) > 9.99999974737875E-05)
                        {
                            if (tmpCells.Any <IntVec3>() && processor(tmpCells))
                            {
                                return(false);
                            }
                            num1 = squared;
                            tmpCells.Clear();
                        }
                        tmpCells.Add(intVec3);
                    }
                }
                if (!tmpCells.Any <IntVec3>())
                {
                    return(false);
                }
                int num3 = processor(tmpCells) ? 1 : 0;
            }
            finally
            {
                //GenRadial.tmpCells.Clear();
                //GenRadial.working = false;
            }
            //}
            return(false);
        }
예제 #13
0
        public virtual float Distance( Thing target, IntVec3 source )
        {
            if ( PathBasedDistance )
            {
                var path = target.Map.pathFinder.FindPath( source, target, 
                    TraverseParms.For( TraverseMode.PassDoors, Danger.Some ), PathEndMode.Touch );
                var cost = path.Found ? path.TotalCost : int.MaxValue;
                path.ReleaseToPool();
                return cost * 2;
            }

            return Mathf.Sqrt( source.DistanceToSquared( target.Position ) ) * 2;
        }
예제 #14
0
        public static Dictionary <ThingDef, float> CalculateDistancesToNearbyClusters2(WildPlantSpawner __instance, IntVec3 c)
        {
            Map map2 = map(__instance);
            //nearbyClusters.Clear();
            //nearbyClustersList.Clear();
            Dictionary <ThingDef, List <float> >           nearbyClusters     = new Dictionary <ThingDef, List <float> >();
            List <KeyValuePair <ThingDef, List <float> > > nearbyClustersList = new List <KeyValuePair <ThingDef, List <float> > >();

            int num = GenRadial.NumCellsInRadius(map2.Biome.MaxWildAndCavePlantsClusterRadius * 2);

            for (int i = 0; i < num; i++)
            {
                IntVec3 intVec = c + GenRadial.RadialPattern[i];
                if (!intVec.InBounds(map2))
                {
                    continue;
                }

                List <Thing> list = map2.thingGrid.ThingsListAtFast(intVec);
                for (int j = 0; j < list.Count; j++)
                {
                    Thing thing = list[j];
                    if (thing.def.category == ThingCategory.Plant && thing.def.plant.GrowsInClusters)
                    {
                        float item = intVec.DistanceToSquared(c);
                        if (!nearbyClusters.TryGetValue(thing.def, out List <float> value))
                        {
                            value = new List <float>(); //SimplePool<List<float>>.Get();
                            nearbyClusters.Add(thing.def, value);
                            nearbyClustersList.Add(new KeyValuePair <ThingDef, List <float> >(thing.def, value));
                        }

                        value.Add(item);
                    }
                }
            }

            //distanceSqToNearbyClusters.Clear();
            Dictionary <ThingDef, float> distanceSqToNearbyClusters = new Dictionary <ThingDef, float>();

            for (int k = 0; k < nearbyClustersList.Count; k++)
            {
                List <float> value2 = nearbyClustersList[k].Value;
                value2.Sort();
                distanceSqToNearbyClusters.Add(nearbyClustersList[k].Key, value2[value2.Count / 2]);
                value2.Clear();
                SimplePool <List <float> > .Return(value2);
            }
            return(distanceSqToNearbyClusters);
        }
        private static void PrintAvoidGridAroundTrapLoc(Building b, ByteGrid avoidGrid)
        {
            Room room = b.Position.GetRoom(b.Map, RegionType.Set_Passable);

            for (int i = 0; i < AvoidGridMaker.TrapRadialCells; i++)
            {
                IntVec3 intVec = b.Position + GenRadial.RadialPattern[i];
                if (intVec.InBounds(b.Map) && intVec.Walkable(b.Map) && intVec.GetRoom(b.Map, RegionType.Set_Passable) == room)
                {
                    float num  = (float)Mathf.Max(1, intVec.DistanceToSquared(b.Position));
                    int   num2 = Mathf.Max(1, Mathf.RoundToInt(80f / num));
                    AvoidGridMaker.IncrementAvoidGrid(avoidGrid, intVec, num2);
                }
            }
        }
예제 #16
0
        private static void PrintAvoidGridAroundTrapLoc(TrapMemory mem, ByteGrid avoidGrid)
        {
            Room room = mem.Cell.GetRoom(mem.map, RegionType.Set_Passable);

            for (int i = 0; i < AvoidGridMaker.TrapRadialCells; i++)
            {
                IntVec3 intVec = mem.Cell + GenRadial.RadialPattern[i];
                if (intVec.InBounds(mem.map) && intVec.Walkable(mem.map) && intVec.GetRoom(mem.map, RegionType.Set_Passable) == room)
                {
                    float num  = (float)Mathf.Max(1, intVec.DistanceToSquared(mem.Cell));
                    int   num2 = Mathf.Max(1, Mathf.RoundToInt((float)(32.0 * mem.PowerPercent / num)));
                    AvoidGridMaker.IncrementAvoidGrid(avoidGrid, intVec, num2);
                }
            }
        }
        private List <Plant> GetLoggableTreesSorted()
        {
            IntVec3 position = manager.map.GetBaseCenter();

            // get a list of trees that are not designated in the logging grounds and are reachable, sorted by yield / distance * 2
            List <Plant> list = manager.map.listerThings.AllThings.Where(IsValidForestryTarget)

                                // OrderBy defaults to ascending, switch sign on current yield to get descending
                                .Select(p => p as Plant)
                                .OrderBy(p => - p.YieldNow() /
                                         (Math.Sqrt(position.DistanceToSquared(p.Position)) * 2))
                                .ToList();

            return(list);
        }
예제 #18
0
        protected override Job TryGiveJob(Pawn pawn)
        {
            IntVec3 intVec = (IntVec3)pawn.mindState.duty.focus;

            if (intVec.IsValid)
            {
                if ((float)intVec.DistanceToSquared(pawn.Position) < 100f && intVec.GetRoom(pawn.Map, RegionType.Set_Passable) == pawn.GetRoom(RegionType.Set_Passable) && intVec.WithinRegions(pawn.Position, pawn.Map, 9, TraverseMode.NoPassClosedDoors, RegionType.Set_Passable))
                {
                    pawn.GetLord().Notify_ReachedDutyLocation(pawn);
                    return(null);
                }
            }
            if (!intVec.IsValid)
            {
                IAttackTarget attackTarget;
                if (!(from x in pawn.Map.attackTargetsCache.GetPotentialTargetsFor(pawn)
                      where !x.ThreatDisabled(pawn) && x.Thing.Faction == Faction.OfPlayer && pawn.CanReach(x.Thing, PathEndMode.OnCell, Danger.Deadly, false, TraverseMode.PassAllDestroyableThings)
                      select x).TryRandomElement(out attackTarget))
                {
                    return(null);
                }
                intVec = attackTarget.Thing.Position;
            }
            Job result;

            if (!pawn.CanReach(intVec, PathEndMode.OnCell, Danger.Deadly, false, TraverseMode.PassAllDestroyableThings))
            {
                result = null;
            }
            else
            {
                using (PawnPath pawnPath = pawn.Map.pathFinder.FindPath(pawn.Position, intVec, TraverseParms.For(pawn, Danger.Deadly, TraverseMode.PassAllDestroyableThings, false), PathEndMode.OnCell))
                {
                    IntVec3 cellBeforeBlocker;
                    Thing   thing = pawnPath.FirstBlockingBuilding(out cellBeforeBlocker, pawn);
                    if (thing != null)
                    {
                        Job job = DigUtility.PassBlockerJob(pawn, thing, cellBeforeBlocker, this.canMineMineables, this.canMineNonMineables);
                        if (job != null)
                        {
                            return(job);
                        }
                    }
                }
                result = new Job(JobDefOf.Goto, intVec, 500, true);
            }
            return(result);
        }
        private List <Pawn> GetHuntableAnimalsSorted()
        {
            // get the 'home' position
            IntVec3 position = manager.map.GetBaseCenter();

            // get a list of alive animals that are not designated in the hunting grounds and are reachable, sorted by meat / distance * 2
            List <Pawn> list = manager.map.mapPawns.AllPawns.Where(p => IsValidHuntingTarget(p))

                               // OrderBy defaults to ascending, switch sign on estimated meat count to get descending
                               .OrderBy(
                p =>
                - p.EstimatedMeatCount() /
                (Math.Sqrt(position.DistanceToSquared(p.Position)) * 2)).ToList();

            return(list);
        }
 private static IntVec3 TryFindEndCell(Map map, List <Pawn> generatedPawns, out IntVec3 end)
 {
     end = IntVec3.Invalid;
     for (int i = 0; i < 8; i++)
     {
         IntVec3 intVec3 = generatedPawns[index : i].Position;
         if (!CellFinder.TryFindRandomEdgeCellWith(validator: (IntVec3 x) => map.reachability.CanReach(start: intVec3, dest: x, peMode: PathEndMode.OnCell, traverseMode: TraverseMode.NoPassClosedDoors, maxDanger: Danger.Deadly), map: map, roadChance: CellFinder.EdgeRoadChance_Ignore, result: out IntVec3 intVec))
         {
             break;
         }
         if (!end.IsValid || intVec.DistanceToSquared(b: intVec3) > end.DistanceToSquared(b: intVec3))
         {
             end = intVec;
         }
     }
     return(end);
 }
예제 #21
0
        private void CalculateDistancesToNearbyClusters(IntVec3 c)
        {
            WildPlantSpawner.nearbyClusters.Clear();
            WildPlantSpawner.nearbyClustersList.Clear();
            int num = GenRadial.NumCellsInRadius((float)(this.map.Biome.MaxWildAndCavePlantsClusterRadius * 2));

            for (int i = 0; i < num; i++)
            {
                IntVec3 intVec = c + GenRadial.RadialPattern[i];
                if (intVec.InBounds(this.map))
                {
                    List <Thing> list = this.map.thingGrid.ThingsListAtFast(intVec);
                    for (int j = 0; j < list.Count; j++)
                    {
                        Thing thing = list[j];
                        if (thing.def.category == ThingCategory.Plant && thing.def.plant.GrowsInClusters)
                        {
                            float        item = (float)intVec.DistanceToSquared(c);
                            List <float> list2;
                            if (!WildPlantSpawner.nearbyClusters.TryGetValue(thing.def, out list2))
                            {
                                list2 = SimplePool <List <float> > .Get();

                                WildPlantSpawner.nearbyClusters.Add(thing.def, list2);
                                WildPlantSpawner.nearbyClustersList.Add(new KeyValuePair <ThingDef, List <float> >(thing.def, list2));
                            }
                            list2.Add(item);
                        }
                    }
                }
            }
            WildPlantSpawner.distanceSqToNearbyClusters.Clear();
            for (int k = 0; k < WildPlantSpawner.nearbyClustersList.Count; k++)
            {
                List <float> value = WildPlantSpawner.nearbyClustersList[k].Value;
                value.Sort();
                WildPlantSpawner.distanceSqToNearbyClusters.Add(WildPlantSpawner.nearbyClustersList[k].Key, value[value.Count / 2]);
                value.Clear();
                SimplePool <List <float> > .Return(value);
            }
        }
        private void CalculateDistancesToNearbyClusters(IntVec3 c)
        {
            nearbyClusters.Clear();
            nearbyClustersList.Clear();
            int num = GenRadial.NumCellsInRadius(map.Biome.MaxWildAndCavePlantsClusterRadius * 2);

            for (int i = 0; i < num; i++)
            {
                IntVec3 intVec = c + GenRadial.RadialPattern[i];
                if (!intVec.InBounds(map))
                {
                    continue;
                }
                List <Thing> list = map.thingGrid.ThingsListAtFast(intVec);
                for (int j = 0; j < list.Count; j++)
                {
                    Thing thing = list[j];
                    if (thing.def.category == ThingCategory.Plant && thing.def.plant.GrowsInClusters)
                    {
                        float item = intVec.DistanceToSquared(c);
                        if (!nearbyClusters.TryGetValue(thing.def, out var value))
                        {
                            value = SimplePool <List <float> > .Get();

                            nearbyClusters.Add(thing.def, value);
                            nearbyClustersList.Add(new KeyValuePair <ThingDef, List <float> >(thing.def, value));
                        }
                        value.Add(item);
                    }
                }
            }
            distanceSqToNearbyClusters.Clear();
            for (int k = 0; k < nearbyClustersList.Count; k++)
            {
                List <float> value2 = nearbyClustersList[k].Value;
                value2.Sort();
                distanceSqToNearbyClusters.Add(nearbyClustersList[k].Key, value2[value2.Count / 2]);
                value2.Clear();
                SimplePool <List <float> > .Return(value2);
            }
        }
예제 #23
0
        protected override Job TryGiveJob(Pawn pawn)
        {
            IntVec3 vector = (IntVec3)pawn.mindState.duty.focus;

            if (vector.IsValid && (float)vector.DistanceToSquared(pawn.Position) < 100 && vector.GetRoom(pawn.Map, RegionType.Set_Passable) == pawn.GetRoom(RegionType.Set_Passable) && vector.WithinRegions(pawn.Position, pawn.Map, 9, TraverseMode.NoPassClosedDoors, RegionType.Set_Passable))
            {
                pawn.GetLord().Notify_ReachedDutyLocation(pawn);
                return(null);
            }
            if (!vector.IsValid)
            {
                IAttackTarget attackTarget;
                if (!(from x in pawn.Map.attackTargetsCache.GetPotentialTargetsFor(pawn)
                      where !x.ThreatDisabled(pawn) && x.Thing.Faction == Faction.OfPlayer && pawn.CanReach(x.Thing, PathEndMode.OnCell, Danger.Deadly, false, TraverseMode.PassAllDestroyableThings)
                      select x).TryRandomElement(out attackTarget))
                {
                    return(null);
                }
                vector = attackTarget.Thing.Position;
            }
            if (!pawn.CanReach(vector, PathEndMode.OnCell, Danger.Deadly, false, TraverseMode.PassAllDestroyableThings))
            {
                return(null);
            }
            using (PawnPath pawnPath = pawn.Map.pathFinder.FindPath(pawn.Position, vector, TraverseParms.For(pawn, Danger.Deadly, TraverseMode.PassAllDestroyableThings, false), PathEndMode.OnCell))
            {
                IntVec3 cellBeforeBlocker;
                Thing   thing = pawnPath.FirstTangleweed(out cellBeforeBlocker, pawn);

                if (thing != null)
                {
                    Job job = AttackPlantUtility.AttackPlant(pawn, thing);
                    if (job != null)
                    {
                        return(job);
                    }
                }
            }
            return(new Job(JobDefOf.Goto, vector, 500, true));
        }
 public static bool TryFindStartAndEndCells(this IncidentWorker_HerdMigration hm, Map map, PawnKindDef kind, out IntVec3 start, out IntVec3 end)
 {
     if (!RCellFinderExtended.TryFindRandomPawnEntryCell(out start, map, kind, CellFinder.EdgeRoadChance_Animal))
     {
         end = IntVec3.Invalid;
         return(false);
     }
     end = IntVec3.Invalid;
     for (int i = 0; i < 8; i++)
     {
         IntVec3 startLocal = start;
         if (!CellFinderExtended.TryFindRandomEdgeCellWith((IntVec3 x) => map.reachability.CanReach(startLocal, x, PathEndMode.OnCell, TraverseMode.NoPassClosedDoors, Danger.Deadly), map, kind, CellFinder.EdgeRoadChance_Ignore, out IntVec3 result))
         {
             break;
         }
         if (!end.IsValid || result.DistanceToSquared(start) > end.DistanceToSquared(start))
         {
             end = result;
         }
     }
     return(end.IsValid);
 }
예제 #25
0
        protected override Job TryGiveJob(Pawn pawn)
        {
            IntVec3 intVec = pawn.mindState.duty.focus.Cell;

            if (intVec.IsValid && (float)intVec.DistanceToSquared(pawn.Position) < 100f && intVec.GetRoom(pawn.Map) == pawn.GetRoom() && intVec.WithinRegions(pawn.Position, pawn.Map, 9, TraverseMode.NoPassClosedDoors))
            {
                pawn.GetLord().Notify_ReachedDutyLocation(pawn);
                return(null);
            }
            if (!intVec.IsValid)
            {
                if (!(from x in pawn.Map.attackTargetsCache.GetPotentialTargetsFor(pawn)
                      where !x.ThreatDisabled(pawn) && x.Thing.Faction == Faction.OfPlayer && pawn.CanReach(x.Thing, PathEndMode.OnCell, Danger.Deadly, canBash: false, TraverseMode.PassAllDestroyableThings)
                      select x).TryRandomElement(out var result))
                {
                    return(null);
                }
                intVec = result.Thing.Position;
            }
            if (!pawn.CanReach(intVec, PathEndMode.OnCell, Danger.Deadly, canBash: false, TraverseMode.PassAllDestroyableThings))
            {
                return(null);
            }
            using (PawnPath path = pawn.Map.pathFinder.FindPath(pawn.Position, intVec, TraverseParms.For(pawn, Danger.Deadly, TraverseMode.PassAllDestroyableThings)))
            {
                IntVec3 cellBefore;
                Thing   thing = path.FirstBlockingBuilding(out cellBefore, pawn);
                if (thing != null)
                {
                    Job job = DigUtility.PassBlockerJob(pawn, thing, cellBefore, canMineMineables, canMineNonMineables);
                    if (job != null)
                    {
                        return(job);
                    }
                }
            }
            return(JobMaker.MakeJob(JobDefOf.Goto, intVec, 500, checkOverrideOnExpiry: true));
        }
예제 #26
0
        private static bool Distance(Thing target, IntVec3 source, out float dist)
        {
            dist = float.MaxValue;
            var pathFinder = target?.MapHeld?.pathFinder;

            if (pathFinder == null)
            {
                return(false);
            }
            if (Settings.opportunisticTakeTool_calcPath)
            {
                var  path  = pathFinder.FindPath(source, target, TraverseParms.For(TraverseMode.PassDoors, Danger.Some), PathEndMode.Touch);
                bool found = path.Found;
                if (found)
                {
                    dist = path.TotalCost * 2;
                }
                path.ReleaseToPool();
                return(found);
            }
            dist = Mathf.Sqrt(source.DistanceToSquared(target.PositionHeld)) * 2;
            return(true);
        }
예제 #27
0
        private int GetDistanceSquaredToExistingEdgeThing(IntVec3 cell, CellRect rect, ThingDef thingDef)
        {
            Map map = BaseGen.globalSettings.map;
            int num = 2147483647;

            foreach (IntVec3 current in rect.EdgeCells)
            {
                List <Thing> thingList = current.GetThingList(map);
                bool         flag      = false;
                for (int i = 0; i < thingList.Count; i++)
                {
                    if (thingList[i].def == thingDef)
                    {
                        flag = true;
                        break;
                    }
                }
                if (flag)
                {
                    num = Mathf.Min(num, cell.DistanceToSquared(current));
                }
            }
            return(num);
        }
예제 #28
0
        private static bool IsSafeDropSpot(IntVec3 cell, Map map, Faction faction, IntVec2?size = null, int distToEdge = 25, int distToHostiles = 35, int distToFires = 15)
        {
            Faction factionBaseFaction = map.ParentFaction ?? Faction.OfPlayer;

            if (size.HasValue)
            {
                foreach (IntVec3 item in GenAdj.OccupiedRect(cell, Rot4.North, size.Value))
                {
                    if (!IsGoodDropSpot(item, map, allowFogged: false, canRoofPunch: false, allowIndoors: false))
                    {
                        return(false);
                    }
                }
            }
            else if (!IsGoodDropSpot(cell, map, allowFogged: false, canRoofPunch: false, allowIndoors: false))
            {
                return(false);
            }
            if (distToEdge > 0 && cell.CloseToEdge(map, distToEdge))
            {
                return(false);
            }
            if (faction != null)
            {
                foreach (IAttackTarget item2 in map.attackTargetsCache.TargetsHostileToFaction(faction))
                {
                    if (!item2.ThreatDisabled(null) && item2.Thing.Position.InHorDistOf(cell, distToHostiles))
                    {
                        return(false);
                    }
                }
            }
            if (!map.reachability.CanReachFactionBase(cell, factionBaseFaction))
            {
                return(false);
            }
            if (size.HasValue)
            {
                foreach (IntVec3 cell2 in CellRect.CenteredOn(cell, size.Value.x, size.Value.z).Cells)
                {
                    if (CellHasCrops(cell2))
                    {
                        return(false);
                    }
                }
            }
            else if (CellHasCrops(cell))
            {
                return(false);
            }
            float minDistToFiresSq = distToFires * distToFires;
            float closestDistSq    = float.MaxValue;
            int   firesCount       = 0;

            RegionTraverser.BreadthFirstTraverse(cell, map, (Region from, Region to) => true, delegate(Region x)
            {
                List <Thing> list = x.ListerThings.ThingsInGroup(ThingRequestGroup.Fire);
                for (int i = 0; i < list.Count; i++)
                {
                    float num = cell.DistanceToSquared(list[i].Position);
                    if (!(num > minDistToFiresSq))
                    {
                        if (num < closestDistSq)
                        {
                            closestDistSq = num;
                        }
                        firesCount++;
                    }
                }
                return(closestDistSq <= minDistToFiresSq && firesCount >= 5);
            }, 15);
            if (closestDistSq <= minDistToFiresSq && firesCount >= 5)
            {
                return(false);
            }
            return(true);

            bool CellHasCrops(IntVec3 c)
            {
                Plant plant = c.GetPlant(map);

                if (plant != null && plant.sown)
                {
                    return(map.zoneManager.ZoneAt(c) is Zone_Growing);
                }
                return(false);
            }
        }
예제 #29
0
        public static bool RandomWanderDestFor(ref IntVec3 __result, Pawn pawn,
                                               IntVec3 root,
                                               float radius,
                                               Func <Pawn, IntVec3, IntVec3, bool> validator,
                                               Danger maxDanger)
        {
            if ((double)radius > 12.0)
            {
                Log.Warning("wanderRadius of " + (object)radius + " is greater than Region.GridSize of " + (object)12 + " and will break.", false);
            }
            bool flag = false;

            if (root.GetRegion(pawn.Map, RegionType.Set_Passable) != null)
            {
                int           maxRegions = Mathf.Max((int)radius / 3, 13);
                List <Region> regions    = new List <Region>();
                CellFinder.AllRegionsNear(regions, root.GetRegion(pawn.Map, RegionType.Set_Passable), maxRegions, TraverseParms.For(pawn, Danger.Deadly, TraverseMode.ByPawn, false), (Predicate <Region>)(reg => (double)reg.extentsClose.ClosestDistSquaredTo(root) <= (double)radius * (double)radius), (Pawn)null, RegionType.Set_Passable);
                if (flag)
                {
                    pawn.Map.debugDrawer.FlashCell(root, 0.6f, nameof(root), 50);
                }
                if (regions.Count > 0)
                {
                    for (int tryIndex = 0; tryIndex < 35; ++tryIndex)
                    {
                        IntVec3 c = IntVec3.Invalid;
                        for (int index = 0; index < 5; ++index)
                        {
                            IntVec3 randomCell = regions.RandomElementByWeight <Region>((Func <Region, float>)(reg => (float)reg.CellCount)).RandomCell;
                            if ((double)randomCell.DistanceToSquared(root) <= (double)radius * (double)radius)
                            {
                                c = randomCell;
                                break;
                            }
                        }
                        if (!c.IsValid)
                        {
                            if (flag)
                            {
                                pawn.Map.debugDrawer.FlashCell(c, 0.32f, "distance", 50);
                            }
                        }
                        else if (!(bool)CanWanderToCell.Invoke(null, new object[] { c, pawn, root, validator, tryIndex, maxDanger }))
                        {
                            if (flag)
                            {
                                pawn.Map.debugDrawer.FlashCell(c, 0.6f, "validation", 50);
                            }
                        }
                        else
                        {
                            if (flag)
                            {
                                pawn.Map.debugDrawer.FlashCell(c, 0.9f, "go!", 50);
                            }
                            regions.Clear();
                            __result = c;
                            return(false);
                        }
                    }
                }
                regions.Clear();
            }
            IntVec3 result;

            if (!CellFinder.TryFindRandomCellNear(root, pawn.Map, Mathf.FloorToInt(radius), (Predicate <IntVec3>)(c =>
            {
                if (!c.InBounds(pawn.Map) || !pawn.CanReach((LocalTargetInfo)c, PathEndMode.OnCell, Danger.None, false, TraverseMode.ByPawn) || c.IsForbidden(pawn))
                {
                    return(false);
                }
                return(validator == null || validator(pawn, c, root));
            }), out result, -1) && !CellFinder.TryFindRandomCellNear(root, pawn.Map, Mathf.FloorToInt(radius), (Predicate <IntVec3>)(c => c.InBounds(pawn.Map) && pawn.CanReach((LocalTargetInfo)c, PathEndMode.OnCell, Danger.None, false, TraverseMode.ByPawn) && !c.IsForbidden(pawn)), out result, -1) && (!CellFinder.TryFindRandomCellNear(root, pawn.Map, Mathf.FloorToInt(radius), (Predicate <IntVec3>)(c => c.InBounds(pawn.Map) && pawn.CanReach((LocalTargetInfo)c, PathEndMode.OnCell, Danger.Deadly, false, TraverseMode.ByPawn)), out result, -1) && !CellFinder.TryFindRandomCellNear(root, pawn.Map, 20, (Predicate <IntVec3>)(c => c.InBounds(pawn.Map) && pawn.CanReach((LocalTargetInfo)c, PathEndMode.OnCell, Danger.None, false, TraverseMode.ByPawn) && !c.IsForbidden(pawn)), out result, -1)) && (!CellFinder.TryFindRandomCellNear(root, pawn.Map, 30, (Predicate <IntVec3>)(c => c.InBounds(pawn.Map) && pawn.CanReach((LocalTargetInfo)c, PathEndMode.OnCell, Danger.Deadly, false, TraverseMode.ByPawn)), out result, -1) && !CellFinder.TryFindRandomCellNear(pawn.Position, pawn.Map, 5, (Predicate <IntVec3>)(c => c.InBounds(pawn.Map) && pawn.CanReach((LocalTargetInfo)c, PathEndMode.OnCell, Danger.Deadly, false, TraverseMode.ByPawn)), out result, -1)))
            {
                result = pawn.Position;
            }
            if (flag)
            {
                pawn.Map.debugDrawer.FlashCell(result, 0.4f, "fallback", 50);
            }
            __result = result;
            return(false);
        }
예제 #30
0
        /// <summary>
        /// Checks whether a collision occurs along flight path within this cell.
        /// </summary>
        /// <param name="cell">Where to check for collisions in</param>
        /// <returns>True if collision occured, false otherwise</returns>
        private bool CheckCellForCollision(IntVec3 cell)
        {
            if (BlockerRegistry.CheckCellForCollisionCallback(this, cell, launcher))
            {
                this.ticksToImpact = 0;
                this.landed        = true;

                this.Impact(null);
                return(true);
            }
            var roofChecked    = false;
            var justWallsRoofs = false;

            //Check for minimum PAWN collision distance
            float distFromOrigin = cell.DistanceToSquared(OriginIV3);
            bool  skipCollision  = !def.projectile.alwaysFreeIntercept &&
                                   (minCollisionSqr <= 1f
                    ? distFromOrigin < 1f
                    : distFromOrigin <= Mathf.Min(144f, minCollisionSqr / 4));

            var mainThingList = new List <Thing>(Map.thingGrid.ThingsListAtFast(cell))
                                .Where(t => justWallsRoofs ? t.def.Fillage == FillCategory.Full : (t is Pawn || t.def.Fillage != FillCategory.None)).ToList();

            //Find pawns in adjacent cells and append them to main list
            if (!justWallsRoofs)
            {
                var adjList = new List <IntVec3>();
                adjList.AddRange(GenAdj.CellsAdjacentCardinal(cell, Rot4.FromAngleFlat(shotRotation), new IntVec2(collisionCheckSize, 0)).ToList());

                //Iterate through adjacent cells and find all the pawns
                foreach (var curCell in adjList)
                {
                    if (curCell != cell && curCell.InBounds(Map))
                    {
                        mainThingList.AddRange(Map.thingGrid.ThingsListAtFast(curCell)
                                               .Where(x => x is Pawn));

                        if (Controller.settings.DebugDrawInterceptChecks)
                        {
                            Map.debugDrawer.FlashCell(curCell, 0.7f);
                        }
                    }
                }
            }

            //If the last position is above the wallCollisionHeight, we should check for roof intersections first
            if (LastPos.y > CollisionVertical.WallCollisionHeight)
            {
                if (TryCollideWithRoof(cell))
                {
                    return(true);
                }
                roofChecked = true;
            }

            foreach (var thing in mainThingList.Distinct().OrderBy(x => (x.DrawPos - LastPos).sqrMagnitude))
            {
                if ((thing == launcher || thing == mount) && !canTargetSelf)
                {
                    continue;
                }

                // Check for collision
                if ((!skipCollision || thing == intendedTarget) && TryCollideWith(thing))
                {
                    return(true);
                }

                // Apply suppression. The height here is NOT that of the bullet in CELL,
                // it is the height at the END OF THE PATH. This is because SuppressionRadius
                // is not considered an EXACT limit.
                if (!justWallsRoofs && ExactPosition.y < SuppressionRadius)
                {
                    var pawn = thing as Pawn;
                    if (pawn != null)
                    {
                        ApplySuppression(pawn);
                    }
                }
            }

            //Finally check for intersecting with a roof (again).
            if (!roofChecked && TryCollideWithRoof(cell))
            {
                return(true);
            }
            return(false);
        }