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); }
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); }
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); }
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); }
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); }