Пример #1
0
        public static Toil GotoCastPosition(TargetIndex targetInd, bool closeIfDowned = false, float maxRangeFactor = 1f)
        {
            Toil toil = new Toil();

            toil.initAction = delegate()
            {
                Pawn    actor  = toil.actor;
                Job     curJob = actor.jobs.curJob;
                Thing   thing  = curJob.GetTarget(targetInd).Thing;
                Pawn    pawn   = thing as Pawn;
                IntVec3 intVec;
                if (!CastPositionFinder.TryFindCastPosition(new CastPositionRequest
                {
                    caster = toil.actor,
                    target = thing,
                    verb = curJob.verbToUse,
                    maxRangeFromTarget = ((closeIfDowned && pawn != null && pawn.Downed) ? Mathf.Min(curJob.verbToUse.verbProps.range, (float)pawn.RaceProps.executionRange) : Mathf.Max(curJob.verbToUse.verbProps.range * maxRangeFactor, 1.42f)),
                    wantCoverFromTarget = false
                }, out intVec))
                {
                    toil.actor.jobs.EndCurrentJob(JobCondition.Incompletable, true);
                }
                else
                {
                    toil.actor.pather.StartPath(intVec, PathEndMode.OnCell);
                    actor.Map.pawnDestinationReservationManager.Reserve(actor, curJob, intVec);
                }
            };
            toil.FailOnDespawnedOrNull(targetInd);
            toil.defaultCompleteMode = ToilCompleteMode.PatherArrival;
            return(toil);
        }
Пример #2
0
        public static Toil GotoCastPosition(TargetIndex targetInd, bool closeIfDowned = false, float maxRangeFactor = 1f)
        {
            Toil toil = new Toil();

            toil.initAction = delegate
            {
                Pawn  actor  = toil.actor;
                Job   curJob = actor.jobs.curJob;
                Thing thing  = curJob.GetTarget(targetInd).Thing;
                Pawn  pawn   = thing as Pawn;
                CastPositionRequest newReq = default(CastPositionRequest);
                newReq.caster              = toil.actor;
                newReq.target              = thing;
                newReq.verb                = curJob.verbToUse;
                newReq.maxRangeFromTarget  = ((!closeIfDowned || pawn == null || !pawn.Downed) ? Mathf.Max(curJob.verbToUse.verbProps.range * maxRangeFactor, 1.42f) : Mathf.Min(curJob.verbToUse.verbProps.range, pawn.RaceProps.executionRange));
                newReq.wantCoverFromTarget = false;
                if (!CastPositionFinder.TryFindCastPosition(newReq, out IntVec3 dest))
                {
                    toil.actor.jobs.EndCurrentJob(JobCondition.Incompletable);
                }
                else
                {
                    toil.actor.pather.StartPath(dest, PathEndMode.OnCell);
                    actor.Map.pawnDestinationReservationManager.Reserve(actor, curJob, dest);
                }
            };
            toil.FailOnDespawnedOrNull(targetInd);
            toil.defaultCompleteMode = ToilCompleteMode.PatherArrival;
            return(toil);
        }
Пример #3
0
        public static Toil GotoCastPosition(TargetIndex targetInd, bool closeIfDowned = false, float maxRangeFactor = 1f)
        {
            Toil toil = new Toil();

            toil.initAction = () =>
            {
                Pawn  actor     = toil.actor;
                Job   curJob    = actor.jobs.curJob;
                Thing targThing = curJob.GetTarget(targetInd).Thing;
                Pawn  targPawn  = targThing as Pawn;

                //We get closer if the target is downed and we can
                CastPositionRequest req = new CastPositionRequest();
                req.caster             = toil.actor;
                req.target             = targThing;
                req.verb               = curJob.verbToUse;
                req.maxRangeFromTarget = (!closeIfDowned || targPawn == null || !targPawn.Downed)
                                        ? Mathf.Max(curJob.verbToUse.verbProps.range * maxRangeFactor, ShootTuning.MeleeRange)
                                        : Mathf.Min(curJob.verbToUse.verbProps.range, targPawn.RaceProps.executionRange);
                req.wantCoverFromTarget = false;

                IntVec3 dest;
                if (!CastPositionFinder.TryFindCastPosition(req, out dest))
                {
                    toil.actor.jobs.EndCurrentJob(JobCondition.Incompletable);
                    return;
                }

                toil.actor.pather.StartPath(dest, PathEndMode.OnCell);

                actor.Map.pawnDestinationReservationManager.Reserve(actor, curJob, dest);
            };
            toil.FailOnDespawnedOrNull(targetInd);
            toil.defaultCompleteMode = ToilCompleteMode.PatherArrival;

            return(toil);
        }
Пример #4
0
        public static bool TryFindCastPosition(CastPositionRequest newReq, out IntVec3 dest)
        {
            CastPositionFinder.req       = newReq;
            CastPositionFinder.casterLoc = CastPositionFinder.req.caster.Position;
            CastPositionFinder.targetLoc = CastPositionFinder.req.target.Position;
            CastPositionFinder.verb      = CastPositionFinder.req.verb;
            CastPositionFinder.avoidGrid = newReq.caster.GetAvoidGrid();
            if (CastPositionFinder.verb == null)
            {
                Log.Error(CastPositionFinder.req.caster + " tried to find casting position without a verb.");
                dest = IntVec3.Invalid;
                return(false);
            }
            if (CastPositionFinder.req.maxRegionsRadius > 0)
            {
                Region region = CastPositionFinder.casterLoc.GetRegion(CastPositionFinder.req.caster.Map, RegionType.Set_Passable);
                if (region == null)
                {
                    Log.Error("TryFindCastPosition requiring region traversal but root region is null.");
                    dest = IntVec3.Invalid;
                    return(false);
                }
                CastPositionFinder.inRadiusMark = Rand.Int;
                RegionTraverser.MarkRegionsBFS(region, null, newReq.maxRegionsRadius, CastPositionFinder.inRadiusMark, RegionType.Set_Passable);
                if (CastPositionFinder.req.maxRangeFromLocus > 0.01f)
                {
                    Region region2 = CastPositionFinder.req.locus.GetRegion(CastPositionFinder.req.caster.Map, RegionType.Set_Passable);
                    if (region2 == null)
                    {
                        Log.Error("locus " + CastPositionFinder.req.locus + " has no region");
                        dest = IntVec3.Invalid;
                        return(false);
                    }
                    if (region2.mark != CastPositionFinder.inRadiusMark)
                    {
                        Log.Error(string.Concat(new object[]
                        {
                            CastPositionFinder.req.caster,
                            " can't possibly get to locus ",
                            CastPositionFinder.req.locus,
                            " as it's not in a maxRegionsRadius of ",
                            CastPositionFinder.req.maxRegionsRadius,
                            ". Overriding maxRegionsRadius."
                        }));
                        CastPositionFinder.req.maxRegionsRadius = 0;
                    }
                }
            }
            CellRect cellRect = CellRect.WholeMap(CastPositionFinder.req.caster.Map);

            if (CastPositionFinder.req.maxRangeFromCaster > 0.01f)
            {
                int      num       = Mathf.CeilToInt(CastPositionFinder.req.maxRangeFromCaster);
                CellRect otherRect = new CellRect(CastPositionFinder.casterLoc.x - num, CastPositionFinder.casterLoc.z - num, num * 2 + 1, num * 2 + 1);
                cellRect.ClipInsideRect(otherRect);
            }
            int      num2       = Mathf.CeilToInt(CastPositionFinder.req.maxRangeFromTarget);
            CellRect otherRect2 = new CellRect(CastPositionFinder.targetLoc.x - num2, CastPositionFinder.targetLoc.z - num2, num2 * 2 + 1, num2 * 2 + 1);

            cellRect.ClipInsideRect(otherRect2);
            if (CastPositionFinder.req.maxRangeFromLocus > 0.01f)
            {
                int      num3       = Mathf.CeilToInt(CastPositionFinder.req.maxRangeFromLocus);
                CellRect otherRect3 = new CellRect(CastPositionFinder.targetLoc.x - num3, CastPositionFinder.targetLoc.z - num3, num3 * 2 + 1, num3 * 2 + 1);
                cellRect.ClipInsideRect(otherRect3);
            }
            CastPositionFinder.bestSpot     = IntVec3.Invalid;
            CastPositionFinder.bestSpotPref = 0.001f;
            CastPositionFinder.maxRangeFromCasterSquared = CastPositionFinder.req.maxRangeFromCaster * CastPositionFinder.req.maxRangeFromCaster;
            CastPositionFinder.maxRangeFromTargetSquared = CastPositionFinder.req.maxRangeFromTarget * CastPositionFinder.req.maxRangeFromTarget;
            CastPositionFinder.maxRangeFromLocusSquared  = CastPositionFinder.req.maxRangeFromLocus * CastPositionFinder.req.maxRangeFromLocus;
            CastPositionFinder.rangeFromTarget           = (CastPositionFinder.req.caster.Position - CastPositionFinder.req.target.Position).LengthHorizontal;
            CastPositionFinder.rangeFromTargetSquared    = (float)(CastPositionFinder.req.caster.Position - CastPositionFinder.req.target.Position).LengthHorizontalSquared;
            CastPositionFinder.optimalRangeSquared       = CastPositionFinder.verb.verbProps.range * 0.8f * (CastPositionFinder.verb.verbProps.range * 0.8f);
            CastPositionFinder.EvaluateCell(CastPositionFinder.req.caster.Position);
            if ((double)CastPositionFinder.bestSpotPref >= 1.0)
            {
                dest = CastPositionFinder.req.caster.Position;
                return(true);
            }
            float    slope    = -1f / CellLine.Between(CastPositionFinder.req.target.Position, CastPositionFinder.req.caster.Position).Slope;
            CellLine cellLine = new CellLine(CastPositionFinder.req.target.Position, slope);
            bool     flag     = cellLine.CellIsAbove(CastPositionFinder.req.caster.Position);

            CellRect.CellRectIterator iterator = cellRect.GetIterator();
            while (!iterator.Done())
            {
                IntVec3 current = iterator.Current;
                if (cellLine.CellIsAbove(current) == flag && cellRect.Contains(current))
                {
                    CastPositionFinder.EvaluateCell(current);
                }
                iterator.MoveNext();
            }
            if (CastPositionFinder.bestSpot.IsValid && CastPositionFinder.bestSpotPref > 0.33f)
            {
                dest = CastPositionFinder.bestSpot;
                return(true);
            }
            CellRect.CellRectIterator iterator2 = cellRect.GetIterator();
            while (!iterator2.Done())
            {
                IntVec3 current2 = iterator2.Current;
                if (cellLine.CellIsAbove(current2) != flag && cellRect.Contains(current2))
                {
                    CastPositionFinder.EvaluateCell(current2);
                }
                iterator2.MoveNext();
            }
            if (CastPositionFinder.bestSpot.IsValid)
            {
                dest = CastPositionFinder.bestSpot;
                return(true);
            }
            dest = CastPositionFinder.casterLoc;
            return(false);
        }
Пример #5
0
        private static void EvaluateCell(IntVec3 c)
        {
            if (CastPositionFinder.maxRangeFromTargetSquared > 0.01f && CastPositionFinder.maxRangeFromTargetSquared < 250000f && (float)(c - CastPositionFinder.req.target.Position).LengthHorizontalSquared > CastPositionFinder.maxRangeFromTargetSquared)
            {
                if (DebugViewSettings.drawCastPositionSearch)
                {
                    CastPositionFinder.req.caster.Map.debugDrawer.FlashCell(c, 0f, "range target", 50);
                }
                return;
            }
            if ((double)CastPositionFinder.maxRangeFromLocusSquared > 0.01 && (float)(c - CastPositionFinder.req.locus).LengthHorizontalSquared > CastPositionFinder.maxRangeFromLocusSquared)
            {
                if (DebugViewSettings.drawCastPositionSearch)
                {
                    CastPositionFinder.req.caster.Map.debugDrawer.FlashCell(c, 0.1f, "range home", 50);
                }
                return;
            }
            if (CastPositionFinder.maxRangeFromCasterSquared > 0.01f)
            {
                CastPositionFinder.rangeFromCasterToCellSquared = (float)(c - CastPositionFinder.req.caster.Position).LengthHorizontalSquared;
                if (CastPositionFinder.rangeFromCasterToCellSquared > CastPositionFinder.maxRangeFromCasterSquared)
                {
                    if (DebugViewSettings.drawCastPositionSearch)
                    {
                        CastPositionFinder.req.caster.Map.debugDrawer.FlashCell(c, 0.2f, "range caster", 50);
                    }
                    return;
                }
            }
            if (!c.Walkable(CastPositionFinder.req.caster.Map))
            {
                return;
            }
            if (CastPositionFinder.req.maxRegionsRadius > 0 && c.GetRegion(CastPositionFinder.req.caster.Map, RegionType.Set_Passable).mark != CastPositionFinder.inRadiusMark)
            {
                if (DebugViewSettings.drawCastPositionSearch)
                {
                    CastPositionFinder.req.caster.Map.debugDrawer.FlashCell(c, 0.64f, "reg radius", 50);
                }
                return;
            }
            if (!CastPositionFinder.req.caster.Map.reachability.CanReach(CastPositionFinder.req.caster.Position, c, PathEndMode.OnCell, TraverseParms.For(CastPositionFinder.req.caster, Danger.Some, TraverseMode.ByPawn, false)))
            {
                if (DebugViewSettings.drawCastPositionSearch)
                {
                    CastPositionFinder.req.caster.Map.debugDrawer.FlashCell(c, 0.4f, "can't reach", 50);
                }
                return;
            }
            float num = CastPositionFinder.CastPositionPreference(c);

            if (CastPositionFinder.avoidGrid != null)
            {
                byte b = CastPositionFinder.avoidGrid[c];
                num *= Mathf.Max(0.1f, (37.5f - (float)b) / 37.5f);
            }
            if (DebugViewSettings.drawCastPositionSearch)
            {
                CastPositionFinder.req.caster.Map.debugDrawer.FlashCell(c, num / 4f, num.ToString("F3"), 50);
            }
            if (num < CastPositionFinder.bestSpotPref)
            {
                return;
            }
            if (!CastPositionFinder.verb.CanHitTargetFrom(c, CastPositionFinder.req.target))
            {
                if (DebugViewSettings.drawCastPositionSearch)
                {
                    CastPositionFinder.req.caster.Map.debugDrawer.FlashCell(c, 0.6f, "can't hit", 50);
                }
                return;
            }
            if (!CastPositionFinder.req.caster.Map.pawnDestinationReservationManager.CanReserve(c, CastPositionFinder.req.caster))
            {
                if (DebugViewSettings.drawCastPositionSearch)
                {
                    CastPositionFinder.req.caster.Map.debugDrawer.FlashCell(c, num * 0.9f, "resvd", 50);
                }
                return;
            }
            if (PawnUtility.KnownDangerAt(c, CastPositionFinder.req.caster))
            {
                if (DebugViewSettings.drawCastPositionSearch)
                {
                    CastPositionFinder.req.caster.Map.debugDrawer.FlashCell(c, 0.9f, "danger", 50);
                }
                return;
            }
            CastPositionFinder.bestSpot     = c;
            CastPositionFinder.bestSpotPref = num;
        }
        public static bool TryFindCastPosition(CastPositionRequest newReq, out IntVec3 dest)
        {
            CastPositionFinder.req       = newReq;
            CastPositionFinder.casterLoc = CastPositionFinder.req.caster.Position;
            CastPositionFinder.targetLoc = CastPositionFinder.req.target.Position;
            CastPositionFinder.verb      = CastPositionFinder.req.verb;
            CastPositionFinder.avoidGrid = newReq.caster.GetAvoidGrid();
            bool result;

            if (CastPositionFinder.verb == null)
            {
                Log.Error(CastPositionFinder.req.caster + " tried to find casting position without a verb.", false);
                dest   = IntVec3.Invalid;
                result = false;
            }
            else
            {
                if (CastPositionFinder.req.maxRegions > 0)
                {
                    Region region = CastPositionFinder.casterLoc.GetRegion(CastPositionFinder.req.caster.Map, RegionType.Set_Passable);
                    if (region == null)
                    {
                        Log.Error("TryFindCastPosition requiring region traversal but root region is null.", false);
                        dest = IntVec3.Invalid;
                        return(false);
                    }
                    CastPositionFinder.inRadiusMark = Rand.Int;
                    RegionTraverser.MarkRegionsBFS(region, null, newReq.maxRegions, CastPositionFinder.inRadiusMark, RegionType.Set_Passable);
                    if (CastPositionFinder.req.maxRangeFromLocus > 0.01f)
                    {
                        Region locusReg = CastPositionFinder.req.locus.GetRegion(CastPositionFinder.req.caster.Map, RegionType.Set_Passable);
                        if (locusReg == null)
                        {
                            Log.Error("locus " + CastPositionFinder.req.locus + " has no region", false);
                            dest = IntVec3.Invalid;
                            return(false);
                        }
                        if (locusReg.mark != CastPositionFinder.inRadiusMark)
                        {
                            CastPositionFinder.inRadiusMark = Rand.Int;
                            RegionTraverser.BreadthFirstTraverse(region, null, delegate(Region r)
                            {
                                r.mark = CastPositionFinder.inRadiusMark;
                                CastPositionFinder.req.maxRegions = CastPositionFinder.req.maxRegions + 1;
                                return(r == locusReg);
                            }, 999999, RegionType.Set_Passable);
                        }
                    }
                }
                CellRect cellRect = CellRect.WholeMap(CastPositionFinder.req.caster.Map);
                if (CastPositionFinder.req.maxRangeFromCaster > 0.01f)
                {
                    int      num       = Mathf.CeilToInt(CastPositionFinder.req.maxRangeFromCaster);
                    CellRect otherRect = new CellRect(CastPositionFinder.casterLoc.x - num, CastPositionFinder.casterLoc.z - num, num * 2 + 1, num * 2 + 1);
                    cellRect.ClipInsideRect(otherRect);
                }
                int      num2       = Mathf.CeilToInt(CastPositionFinder.req.maxRangeFromTarget);
                CellRect otherRect2 = new CellRect(CastPositionFinder.targetLoc.x - num2, CastPositionFinder.targetLoc.z - num2, num2 * 2 + 1, num2 * 2 + 1);
                cellRect.ClipInsideRect(otherRect2);
                if (CastPositionFinder.req.maxRangeFromLocus > 0.01f)
                {
                    int      num3       = Mathf.CeilToInt(CastPositionFinder.req.maxRangeFromLocus);
                    CellRect otherRect3 = new CellRect(CastPositionFinder.targetLoc.x - num3, CastPositionFinder.targetLoc.z - num3, num3 * 2 + 1, num3 * 2 + 1);
                    cellRect.ClipInsideRect(otherRect3);
                }
                CastPositionFinder.bestSpot     = IntVec3.Invalid;
                CastPositionFinder.bestSpotPref = 0.001f;
                CastPositionFinder.maxRangeFromCasterSquared = CastPositionFinder.req.maxRangeFromCaster * CastPositionFinder.req.maxRangeFromCaster;
                CastPositionFinder.maxRangeFromTargetSquared = CastPositionFinder.req.maxRangeFromTarget * CastPositionFinder.req.maxRangeFromTarget;
                CastPositionFinder.maxRangeFromLocusSquared  = CastPositionFinder.req.maxRangeFromLocus * CastPositionFinder.req.maxRangeFromLocus;
                CastPositionFinder.rangeFromTarget           = (CastPositionFinder.req.caster.Position - CastPositionFinder.req.target.Position).LengthHorizontal;
                CastPositionFinder.rangeFromTargetSquared    = (float)(CastPositionFinder.req.caster.Position - CastPositionFinder.req.target.Position).LengthHorizontalSquared;
                CastPositionFinder.optimalRangeSquared       = CastPositionFinder.verb.verbProps.range * 0.8f * (CastPositionFinder.verb.verbProps.range * 0.8f);
                CastPositionFinder.EvaluateCell(CastPositionFinder.req.caster.Position);
                if ((double)CastPositionFinder.bestSpotPref >= 1.0)
                {
                    dest   = CastPositionFinder.req.caster.Position;
                    result = true;
                }
                else
                {
                    float    slope    = -1f / CellLine.Between(CastPositionFinder.req.target.Position, CastPositionFinder.req.caster.Position).Slope;
                    CellLine cellLine = new CellLine(CastPositionFinder.req.target.Position, slope);
                    bool     flag     = cellLine.CellIsAbove(CastPositionFinder.req.caster.Position);
                    Profiler.BeginSample("TryFindCastPosition scan near side");
                    CellRect.CellRectIterator iterator = cellRect.GetIterator();
                    while (!iterator.Done())
                    {
                        IntVec3 c = iterator.Current;
                        if (cellLine.CellIsAbove(c) == flag && cellRect.Contains(c))
                        {
                            CastPositionFinder.EvaluateCell(c);
                        }
                        iterator.MoveNext();
                    }
                    Profiler.EndSample();
                    if (CastPositionFinder.bestSpot.IsValid && CastPositionFinder.bestSpotPref > 0.33f)
                    {
                        dest   = CastPositionFinder.bestSpot;
                        result = true;
                    }
                    else
                    {
                        Profiler.BeginSample("TryFindCastPosition scan far side");
                        CellRect.CellRectIterator iterator2 = cellRect.GetIterator();
                        while (!iterator2.Done())
                        {
                            IntVec3 c2 = iterator2.Current;
                            if (cellLine.CellIsAbove(c2) != flag && cellRect.Contains(c2))
                            {
                                CastPositionFinder.EvaluateCell(c2);
                            }
                            iterator2.MoveNext();
                        }
                        Profiler.EndSample();
                        if (CastPositionFinder.bestSpot.IsValid)
                        {
                            dest   = CastPositionFinder.bestSpot;
                            result = true;
                        }
                        else
                        {
                            dest   = CastPositionFinder.casterLoc;
                            result = false;
                        }
                    }
                }
            }
            return(result);
        }