public static bool BestAttackTarget(ref IAttackTarget __result, 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, bool canTakeTargetsCloserThanEffectiveMinRange = true) { Thing searcherThing = searcher.Thing; Pawn searcherPawn = searcher as Pawn; Verb verb = searcher.CurrentEffectiveVerb; if (verb == null) { Log.Error("BestAttackTarget with " + searcher.ToStringSafe <IAttackTargetSearcher>() + " who has no attack verb.", false); __result = null; return(false); } bool onlyTargetMachines = verb.IsEMP(); float minDistSquared = minDist * minDist; float num = maxTravelRadiusFromLocus + verb.verbProps.range; float maxLocusDistSquared = num * num; Func <IntVec3, bool> losValidator = null; if ((flags & TargetScanFlags.LOSBlockableByGas) != TargetScanFlags.None) { 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 (minDistSquared > 0f && (float)(searcherThing.Position - thing.Position).LengthHorizontalSquared < minDistSquared) { return(false); } if (!canTakeTargetsCloserThanEffectiveMinRange) { float num2 = verb.verbProps.EffectiveMinRange(thing, searcherThing); if (num2 > 0f && (float)(searcherThing.Position - thing.Position).LengthHorizontalSquared < num2 * num2) { return(false); } } if (maxTravelRadiusFromLocus < 9999f && (float)(thing.Position - locus).LengthHorizontalSquared > maxLocusDistSquared) { return(false); } if (!searcherThing.HostileTo(thing)) { return(false); } if (validator != null && !validator(thing)) { return(false); } if (searcherPawn != null) { Lord lord = searcherPawn.GetLord(); if (lord != null && !lord.LordJob.ValidateAttackTarget(searcherPawn, thing)) { return(false); } } if ((flags & TargetScanFlags.NeedNotUnderThickRoof) != TargetScanFlags.None) { RoofDef roof = thing.Position.GetRoof(thing.Map); if (roof != null && roof.isThickRoof) { return(false); } } if ((flags & TargetScanFlags.NeedLOSToAll) != TargetScanFlags.None) { if (losValidator != null && (!losValidator(searcherThing.Position) || !losValidator(thing.Position))) { return(false); } if (!searcherThing.CanSee(thing, losValidator)) { if (t is Pawn) { if ((flags & TargetScanFlags.NeedLOSToPawns) != TargetScanFlags.None) { return(false); } } else if ((flags & TargetScanFlags.NeedLOSToNonPawns) != TargetScanFlags.None) { return(false); } } } if (((flags & TargetScanFlags.NeedThreat) != TargetScanFlags.None || (flags & TargetScanFlags.NeedAutoTargetable) != TargetScanFlags.None) && t.ThreatDisabled(searcher)) { return(false); } if ((flags & TargetScanFlags.NeedAutoTargetable) != TargetScanFlags.None && !AttackTargetFinder.IsAutoTargetable(t)) { return(false); } if ((flags & TargetScanFlags.NeedActiveThreat) != TargetScanFlags.None && !GenHostility.IsActiveThreatTo(t, searcher.Thing.Faction)) { return(false); } Pawn pawn = t as Pawn; if (onlyTargetMachines && pawn != null && pawn.RaceProps.IsFlesh) { return(false); } if ((flags & TargetScanFlags.NeedNonBurning) != TargetScanFlags.None && thing.IsBurning()) { return(false); } if (searcherThing.def.race != null && searcherThing.def.race.intelligence >= Intelligence.Humanlike) { 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; using (CellRect.Enumerator enumerator = thing.OccupiedRect().GetEnumerator()) { while (enumerator.MoveNext()) { if (!enumerator.Current.Fogged(thing.Map)) { flag2 = true; break; } } } if (!flag2) { return(false); } } return(true); }; if (HasRangedAttack(searcher) && (searcherPawn == null || !searcherPawn.InAggroMentalState)) { List <IAttackTarget> tmpTargets = new List <IAttackTarget>(); //AttackTargetFinder.tmpTargets.Clear(); tmpTargets.AddRange(searcherThing.Map.attackTargetsCache.GetPotentialTargetsFor(searcher)); if ((flags & TargetScanFlags.NeedReachable) != TargetScanFlags.None) { Predicate <IAttackTarget> oldValidator = innerValidator; innerValidator = ((IAttackTarget t) => oldValidator(t) && CanReach(searcherThing, t.Thing, canBash)); } bool flag = false; for (int i = 0; i < tmpTargets.Count; i++) { IAttackTarget attackTarget = tmpTargets[i]; if (attackTarget.Thing.Position.InHorDistOf(searcherThing.Position, maxDist) && innerValidator(attackTarget) && CanShootAtFromCurrentPosition(attackTarget, searcher, verb)) { flag = true; break; } } IAttackTarget result = null; if (flag) { tmpTargets.RemoveAll((IAttackTarget x) => !x.Thing.Position.InHorDistOf(searcherThing.Position, maxDist) || !innerValidator(x)); _ = GetRandomShootingTargetByScore(ref result, tmpTargets, searcher, verb); } else { Predicate <Thing> validator2; if ((flags & TargetScanFlags.NeedReachableIfCantHitFromMyPos) != TargetScanFlags.None && (flags & TargetScanFlags.NeedReachable) == TargetScanFlags.None) { validator2 = ((Thing t) => innerValidator((IAttackTarget)t) && (CanReach(searcherThing, t, canBash) || CanShootAtFromCurrentPosition((IAttackTarget)t, searcher, verb))); } else { validator2 = ((Thing t) => innerValidator((IAttackTarget)t)); } result = (IAttackTarget)GenClosest.ClosestThing_Global(searcherThing.Position, tmpTargets, maxDist, validator2, null); } tmpTargets.Clear(); __result = result; return(false); } if (searcherPawn != null && searcherPawn.mindState.duty != null && searcherPawn.mindState.duty.radius > 0f && !searcherPawn.InMentalState) { Predicate <IAttackTarget> oldValidator = innerValidator; innerValidator = ((IAttackTarget t) => oldValidator(t) && t.Thing.Position.InHorDistOf(searcherPawn.mindState.duty.focus.Cell, searcherPawn.mindState.duty.radius)); } IAttackTarget attackTarget2 = (IAttackTarget)GenClosest.ClosestThingReachable(searcherThing.Position, searcherThing.Map, ThingRequest.ForGroup(ThingRequestGroup.AttackTarget), PathEndMode.Touch, TraverseParms.For(searcherPawn, Danger.Deadly, TraverseMode.ByPawn, canBash), maxDist, (Thing x) => innerValidator((IAttackTarget)x), null, 0, (maxDist > 800f) ? -1 : 40, false, RegionType.Set_Passable, false); if (attackTarget2 != null && PawnUtility.ShouldCollideWithPawns(searcherPawn)) { IAttackTarget attackTarget3 = FindBestReachableMeleeTarget(innerValidator, searcherPawn, maxDist, canBash); if (attackTarget3 != null) { float lengthHorizontal = (searcherPawn.Position - attackTarget2.Thing.Position).LengthHorizontal; float lengthHorizontal2 = (searcherPawn.Position - attackTarget3.Thing.Position).LengthHorizontal; if (Mathf.Abs(lengthHorizontal - lengthHorizontal2) < 50f) { attackTarget2 = attackTarget3; } } } __result = attackTarget2; return(false); }
public bool ThreatDisabled(IAttackTargetSearcher disabledFor) { return(true); }
private static bool CanShootAtFromCurrentPosition(IAttackTarget target, IAttackTargetSearcher searcher, Verb verb) { return(verb?.CanHitTargetFrom(searcher.Thing.Position, target.Thing) ?? false); }
private static IAttackTarget GetRandomShootingTargetByScore(List <IAttackTarget> targets, IAttackTargetSearcher searcher, Verb verb) { Pair <IAttackTarget, float> pair = default(Pair <IAttackTarget, float>); if (((IEnumerable <Pair <IAttackTarget, float> >)AttackTargetFinder.GetAvailableShootingTargetsByScore(targets, searcher, verb)).TryRandomElementByWeight <Pair <IAttackTarget, float> >((Func <Pair <IAttackTarget, float>, float>)((Pair <IAttackTarget, float> x) => x.Second), out pair)) { return(pair.First); } return(null); }
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 ((byte)(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 > 0f && (float)(searcherThing.Position - thing.Position).LengthHorizontalSquared < minDistanceSquared) { return(false); } if (maxTravelRadiusFromLocus < 9999f && (float)(thing.Position - locus).LengthHorizontalSquared > maxLocusDistSquared) { return(false); } if (!searcherThing.HostileTo(thing)) { return(false); } if (validator != null && !validator(thing)) { return(false); } if ((byte)(flags & TargetScanFlags.NeedLOSToAll) != 0 && !searcherThing.CanSee(thing, losValidator)) { if (t is Pawn) { if ((byte)(flags & TargetScanFlags.NeedLOSToPawns) != 0) { return(false); } } else if ((byte)(flags & TargetScanFlags.NeedLOSToNonPawns) != 0) { return(false); } } if ((byte)(flags & TargetScanFlags.NeedThreat) != 0 && t.ThreatDisabled(searcher)) { return(false); } Pawn pawn = t as Pawn; if (onlyTargetMachines && pawn != null && pawn.RaceProps.IsFlesh) { return(false); } if ((byte)(flags & TargetScanFlags.NeedNonBurning) != 0 && thing.IsBurning()) { return(false); } if (searcherThing.def.race != null && searcherThing.def.race.intelligence >= Intelligence.Humanlike) { CompExplosive compExplosive = thing.TryGetCompFast <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; foreach (var iterator in thing.OccupiedRect()) { if (!iterator.Fogged(thing.Map)) { flag2 = true; break; } } if (!flag2) { return(false); } } return(true); }; if (AdeptusAttackTargetFinder.HasRangedAttack(searcher)) { //Log.Warning("Finder: Range detected. Verb is " + verb); //Log.Warning("Finder: Pawn " + searcherPawn.Faction); AdeptusAttackTargetFinder.tmpTargets.Clear(); //This needs to be fixed. Can't use searcherThing. Doing this the hard way. //Set request for all attackable. ThingRequest thingReq = ThingRequest.ForGroup(ThingRequestGroup.AttackTarget); IEnumerable <Thing> searchSet = searcherThing.Map.listerThings.ThingsMatching(thingReq); foreach (IAttackTarget iTarget in searchSet) { AdeptusAttackTargetFinder.tmpTargets.Add(iTarget); } if ((byte)(flags & TargetScanFlags.NeedReachable) != 0) { Predicate <IAttackTarget> oldValidator = innerValidator; innerValidator = ((IAttackTarget t) => oldValidator(t) && AdeptusAttackTargetFinder.CanReach(searcherThing, t.Thing, canBash)); } bool flag = false; if (searcherThing.Faction != Faction.OfPlayer) { //Log.Warning("Finder: Target available : " + ARA_AttackTargetFinder.tmpTargets.Count); for (int i = 0; i < AdeptusAttackTargetFinder.tmpTargets.Count; i++) { IAttackTarget attackTarget = AdeptusAttackTargetFinder.tmpTargets[i]; if (attackTarget.Thing.Position.InHorDistOf(searcherThing.Position, maxDist) && innerValidator(attackTarget) && AdeptusAttackTargetFinder.CanShootAtFromCurrentPosition(attackTarget, searcher, verb)) { //Log.Warning("Finder: flag is true"); flag = true; break; } } } IAttackTarget result; if (flag) { //Log.Warning("Finder: FlagTrue result"); AdeptusAttackTargetFinder.tmpTargets.RemoveAll((IAttackTarget x) => !x.Thing.Position.InHorDistOf(searcherThing.Position, maxDist) || !innerValidator(x)); //Log.Warning("Finder: Target Avaliable : " + ARA_AttackTargetFinder.tmpTargets.Count); result = AdeptusAttackTargetFinder.GetRandomShootingTargetByScore(AdeptusAttackTargetFinder.tmpTargets, searcher, verb); } else { Predicate <Thing> validator2; if ((byte)(flags & TargetScanFlags.NeedReachableIfCantHitFromMyPos) != 0 && (byte)(flags & TargetScanFlags.NeedReachable) == 0) { //Log.Warning("Finder: Needs reachable"); validator2 = ((Thing t) => innerValidator((IAttackTarget)t) && (AdeptusAttackTargetFinder.CanReach(searcherThing, t, canBash) || AdeptusAttackTargetFinder.CanShootAtFromCurrentPosition((IAttackTarget)t, searcher, verb))); } else { //Log.Warning("Finder: Running normal validator"); validator2 = ((Thing t) => innerValidator((IAttackTarget)t)); } result = (IAttackTarget)GenClosest.ClosestThing_Global(searcherThing.Position, AdeptusAttackTargetFinder.tmpTargets, maxDist, validator2, null); } AdeptusAttackTargetFinder.tmpTargets.Clear(); //Log.Warning("Trying to return result " + result); return(result); } //Log.Warning("Returning Null"); return(null); }
public static IAttackTarget BestShootTargetFromCurrentPosition(IAttackTargetSearcher searcher, Predicate <Thing> validator, float maxDistance, float minDistance, TargetScanFlags flags) { return(AdeptusAttackTargetFinder.BestAttackTarget(searcher, flags, validator, minDistance, maxDistance, default(IntVec3), 3.40282347E+38f, false)); }
private static float FriendlyFireBlastRadiusTargetScoreOffset(IAttackTarget target, IAttackTargetSearcher searcher, Verb verb) { if (verb.verbProps.ai_AvoidFriendlyFireRadius <= 0f) { return(0f); } Map map = target.Thing.Map; IntVec3 position = target.Thing.Position; int num = GenRadial.NumCellsInRadius(verb.verbProps.ai_AvoidFriendlyFireRadius); float num2 = 0f; for (int i = 0; i < num; i++) { IntVec3 intVec = position + GenRadial.RadialPattern[i]; if (intVec.InBounds(map)) { bool flag = true; List <Thing> thingList = intVec.GetThingList(map); for (int j = 0; j < thingList.Count; j++) { if (thingList[j] is IAttackTarget && thingList[j] != target) { if (flag) { if (!GenSight.LineOfSight(position, intVec, map, skipFirstCell: true)) { break; } flag = false; } float num3 = (thingList[j] == searcher) ? 40f : ((!(thingList[j] is Pawn)) ? 10f : ((!thingList[j].def.race.Animal) ? 18f : 7f)); num2 = ((!searcher.Thing.HostileTo(thingList[j])) ? (num2 - num3) : (num2 + num3 * 0.6f)); } } } } return(num2); }
private static IAttackTarget GetRandomShootingTargetByScore(List <IAttackTarget> targets, IAttackTargetSearcher searcher, Verb verb) { Pair <IAttackTarget, float> pair; if (AdeptusAttackTargetFinder.GetAvailableShootingTargetsByScore(targets, searcher, verb).TryRandomElementByWeight((Pair <IAttackTarget, float> x) => x.Second, out pair)) { return(pair.First); } return(null); }
private static List <Pair <IAttackTarget, float> > GetAvailableShootingTargetsByScore(List <IAttackTarget> rawTargets, IAttackTargetSearcher searcher, Verb verb) { availableShootingTargets.Clear(); if (rawTargets.Count == 0) { return(availableShootingTargets); } tmpTargetScores.Clear(); tmpCanShootAtTarget.Clear(); float num = 0f; IAttackTarget attackTarget = null; for (int i = 0; i < rawTargets.Count; i++) { tmpTargetScores.Add(float.MinValue); tmpCanShootAtTarget.Add(item: false); if (rawTargets[i] == searcher) { continue; } bool flag = CanShootAtFromCurrentPosition(rawTargets[i], searcher, verb); tmpCanShootAtTarget[i] = flag; if (flag) { float shootingTargetScore = GetShootingTargetScore(rawTargets[i], searcher, verb); tmpTargetScores[i] = shootingTargetScore; if (attackTarget == null || shootingTargetScore > num) { attackTarget = rawTargets[i]; num = shootingTargetScore; } } } if (num < 1f) { if (attackTarget != null) { availableShootingTargets.Add(new Pair <IAttackTarget, float>(attackTarget, 1f)); } } else { float num2 = num - 30f; for (int j = 0; j < rawTargets.Count; j++) { if (rawTargets[j] != searcher && tmpCanShootAtTarget[j]) { float num3 = tmpTargetScores[j]; if (num3 >= num2) { float second = Mathf.InverseLerp(num - 30f, num, num3); availableShootingTargets.Add(new Pair <IAttackTarget, float>(rawTargets[j], second)); } } } } return(availableShootingTargets); }
private static float FriendlyFireConeTargetScoreOffset(IAttackTarget target, IAttackTargetSearcher searcher, Verb verb) { Pawn pawn = searcher.Thing as Pawn; if (pawn == null) { return(0f); } if ((int)pawn.RaceProps.intelligence < 1) { return(0f); } if (pawn.RaceProps.IsMechanoid) { return(0f); } Verb_Shoot verb_Shoot = verb as Verb_Shoot; if (verb_Shoot == null) { return(0f); } ThingDef defaultProjectile = verb_Shoot.verbProps.defaultProjectile; if (defaultProjectile == null) { return(0f); } if (defaultProjectile.projectile.flyOverhead) { return(0f); } Map map = pawn.Map; ShotReport report = ShotReport.HitReportFor(pawn, verb, (Thing)target); float radius = Mathf.Max(VerbUtility.CalculateAdjustedForcedMiss(verb.verbProps.forcedMissRadius, report.ShootLine.Dest - report.ShootLine.Source), 1.5f); IEnumerable <IntVec3> enumerable = (from dest in GenRadial.RadialCellsAround(report.ShootLine.Dest, radius, useCenter: true) where dest.InBounds(map) select new ShootLine(report.ShootLine.Source, dest)).SelectMany((ShootLine line) => line.Points().Concat(line.Dest).TakeWhile((IntVec3 pos) => pos.CanBeSeenOverFast(map))).Distinct(); float num = 0f; foreach (IntVec3 item in enumerable) { float num2 = VerbUtility.InterceptChanceFactorFromDistance(report.ShootLine.Source.ToVector3Shifted(), item); if (!(num2 <= 0f)) { List <Thing> thingList = item.GetThingList(map); for (int i = 0; i < thingList.Count; i++) { Thing thing = thingList[i]; if (thing is IAttackTarget && thing != target) { float num3 = (thing == searcher) ? 40f : ((!(thing is Pawn)) ? 10f : (thing.def.race.Animal ? 7f : 18f)); num3 *= num2; num3 = ((!searcher.Thing.HostileTo(thing)) ? (num3 * -1f) : (num3 * 0.6f)); num += num3; } } } } return(num); }
public static bool GetPotentialTargetsFor(AttackTargetsCache __instance, ref List <IAttackTarget> __result, IAttackTargetSearcher th) { Thing thing = th.Thing; List <IAttackTarget> targets = new List <IAttackTarget>(); Faction faction = thing.Faction; if (faction != null) { foreach (IAttackTarget attackTarget in TargetsHostileToFaction2(__instance, faction)) { if (thing.HostileTo(attackTarget.Thing)) { targets.Add(attackTarget); } } } foreach (Pawn pawn in pawnsInAggroMentalState(__instance)) { if (thing.HostileTo(pawn)) { targets.Add(pawn); } } foreach (Pawn pawn2 in factionlessHumanlikes(__instance)) { if (thing.HostileTo(pawn2)) { targets.Add(pawn2); } } Pawn pawn3 = th as Pawn; if (pawn3 != null && PrisonBreakUtility.IsPrisonBreaking(pawn3)) { Faction hostFaction = pawn3.guest.HostFaction; List <Pawn> list = map(__instance).mapPawns.SpawnedPawnsInFaction(hostFaction); for (int i = 0; i < list.Count; i++) { if (thing.HostileTo(list[i])) { targets.Add(list[i]); } } } __result = targets; return(false); }
public static bool GetPotentialTargetsFor(AttackTargetsCache __instance, ref List <IAttackTarget> __result, IAttackTargetSearcher th) { Thing thing = th.Thing; List <IAttackTarget> targets = new List <IAttackTarget>(); Faction faction = thing.Faction; if (faction != null) { List <IAttackTarget> snapshotTargetsHostileToFactionList = getTargetsHostileToFactionList(__instance, faction); foreach (IAttackTarget item in snapshotTargetsHostileToFactionList) { if (thing.HostileTo(item.Thing)) { targets.Add(item); } } } if (pawnsInAggroMentalStateDict.TryGetValue(__instance, out List <Pawn> listPawnsInAggroMentalState)) { foreach (Pawn pawn in listPawnsInAggroMentalState) { if (thing.HostileTo(pawn)) { targets.Add(pawn); } } } if (factionlessHumanlikesDict.TryGetValue(__instance, out List <Pawn> listFactionlessHumanlikes)) { foreach (Pawn pawn2 in listFactionlessHumanlikes) { if (thing.HostileTo(pawn2)) { targets.Add(pawn2); } } } if (th is Pawn pawn3 && PrisonBreakUtility.IsPrisonBreaking(pawn3)) { Faction hostFaction = pawn3.guest.HostFaction; List <Pawn> list = map(__instance).mapPawns.SpawnedPawnsInFaction(hostFaction); for (int i = 0; i < list.Count; i++) { if (thing.HostileTo(list[i])) { targets.Add(list[i]); } } } __result = targets; return(false); }
public bool ThreatDisabled(IAttackTargetSearcher disabledFor) { return(_deployed.ThreatDisabled(disabledFor)); }
public static void IgnoreShoulderTurret(Building_Turret_Shoulder __instance, ref bool __result, IAttackTargetSearcher disabledFor) { bool selected__instance = Find.Selector.SelectedObjects.Contains(__instance); bool shouldturret = false; if (__instance != null) { if (__instance is Building_Turret_Shoulder) { shouldturret = true; } } __result = (__result || shouldturret); }
private static float AdjustedRange(float original, Verb verb, IAttackTargetSearcher searcher) { return(TrenchUtility.FinalAdjustedRangeFromTerrain(original, verb, searcher.Thing)); }
private static bool HasRangedAttack(IAttackTargetSearcher t) { Verb currentEffectiveVerb = t.CurrentEffectiveVerb; return(currentEffectiveVerb != null && !currentEffectiveVerb.verbProps.IsMeleeAttack); }
public static IAttackTarget BestAttackTarget(IAttackTargetSearcher searcher, Verb verb, TargetScanFlags flags, Predicate <Thing> validator = null, float minDist = 0f, float maxDist = 9999f, IntVec3 locus = default(IntVec3), float maxTravelRadiusFromLocus = 3.40282347E+38f, bool canBash = false, bool canTakeTargetsCloserThanEffectiveMinRange = true) { Thing searcherThing = searcher.Thing; Pawn searcherPawn = searcher as Pawn; if (verb == null) { Log.Error("BestAttackTarget with " + searcher.ToStringSafe <IAttackTargetSearcher>() + " who has no attack verb."); return(null); } bool onlyTargetMachines = verb.IsEMP(); float minDistSquared = minDist * minDist; float num = maxTravelRadiusFromLocus + verb.verbProps.range; float maxLocusDistSquared = num * num; Func <IntVec3, bool> losValidator = null; if ((byte)(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 (minDistSquared > 0f && (float)(searcherThing.Position - thing.Position).LengthHorizontalSquared < minDistSquared) { return(false); } if (!canTakeTargetsCloserThanEffectiveMinRange) { float num2 = verb.verbProps.EffectiveMinRange(thing, searcherThing); if (num2 > 0f && (float)(searcherThing.Position - thing.Position).LengthHorizontalSquared < num2 * num2) { return(false); } } if (maxTravelRadiusFromLocus < 9999f && (float)(thing.Position - locus).LengthHorizontalSquared > maxLocusDistSquared) { return(false); } if (!searcherThing.HostileTo(thing)) { return(false); } if (validator != null && !validator(thing)) { return(false); } if (searcherPawn != null) { Lord lord = searcherPawn.GetLord(); if (lord != null && !lord.LordJob.ValidateAttackTarget(searcherPawn, thing)) { return(false); } } if ((byte)(flags & TargetScanFlags.NeedLOSToAll) != 0 && !searcherThing.CanSee(thing, losValidator)) { if (t is Pawn) { if ((byte)(flags & TargetScanFlags.NeedLOSToPawns) != 0) { return(false); } } else if ((byte)(flags & TargetScanFlags.NeedLOSToNonPawns) != 0) { return(false); } } if ((byte)(flags & TargetScanFlags.NeedThreat) != 0 && t.ThreatDisabled(searcher)) { return(false); } if (onlyTargetMachines && t is Pawn pawn && pawn.RaceProps.IsFlesh) { return(false); } if ((byte)(flags & TargetScanFlags.NeedNonBurning) != 0 && thing.IsBurning()) { return(false); } if (searcherThing.def.race != null && searcherThing.def.race.intelligence >= Intelligence.Humanlike) { 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; foreach (IntVec3 cellRect in thing.OccupiedRect()) { if (cellRect.Fogged(thing.Map)) { flag2 = true; break; } } if (!flag2) { return(false); } } return(true); }; if (PCF_AttackTargetFinder.HasRangedAttack(searcher, verb)) { PCF_AttackTargetFinder.tmpTargets.Clear(); PCF_AttackTargetFinder.tmpTargets.AddRange(searcherThing.Map.attackTargetsCache.GetPotentialTargetsFor(searcher)); if ((byte)(flags & TargetScanFlags.NeedReachable) != 0) { Predicate <IAttackTarget> oldValidator = innerValidator; innerValidator = ((IAttackTarget t) => oldValidator(t) && PCF_AttackTargetFinder.CanReach(searcherThing, t.Thing, canBash)); } bool flag = false; for (int i = 0; i < PCF_AttackTargetFinder.tmpTargets.Count; i++) { IAttackTarget attackTarget = PCF_AttackTargetFinder.tmpTargets[i]; if (attackTarget.Thing.Position.InHorDistOf(searcherThing.Position, maxDist) && innerValidator(attackTarget) && PCF_AttackTargetFinder.CanShootAtFromCurrentPosition(attackTarget, searcher, verb)) { flag = true; break; } } IAttackTarget result; if (flag) { PCF_AttackTargetFinder.tmpTargets.RemoveAll((IAttackTarget x) => !x.Thing.Position.InHorDistOf(searcherThing.Position, maxDist) || !innerValidator(x)); result = PCF_AttackTargetFinder.GetRandomShootingTargetByScore(PCF_AttackTargetFinder.tmpTargets, searcher, verb); } else { Predicate <Thing> validator2; if ((byte)(flags & TargetScanFlags.NeedReachableIfCantHitFromMyPos) != 0 && (byte)(flags & TargetScanFlags.NeedReachable) == 0) { validator2 = ((Thing t) => innerValidator((IAttackTarget)t) && (PCF_AttackTargetFinder.CanReach(searcherThing, t, canBash) || PCF_AttackTargetFinder.CanShootAtFromCurrentPosition((IAttackTarget)t, searcher, verb))); } else { validator2 = ((Thing t) => innerValidator((IAttackTarget)t)); } result = (IAttackTarget)GenClosest.ClosestThing_Global(searcherThing.Position, PCF_AttackTargetFinder.tmpTargets, maxDist, validator2, null); } PCF_AttackTargetFinder.tmpTargets.Clear(); return(result); } if (searcherPawn != null && searcherPawn.mindState.duty != null && searcherPawn.mindState.duty.radius > 0f && !searcherPawn.InMentalState) { Predicate <IAttackTarget> oldValidator = innerValidator; innerValidator = ((IAttackTarget t) => oldValidator(t) && t.Thing.Position.InHorDistOf(searcherPawn.mindState.duty.focus.Cell, searcherPawn.mindState.duty.radius)); } IntVec3 position = searcherThing.Position; Map map = searcherThing.Map; ThingRequest thingReq = ThingRequest.ForGroup(ThingRequestGroup.AttackTarget); PathEndMode peMode = PathEndMode.Touch; Pawn searcherPawn2 = searcherPawn; Danger maxDanger = Danger.Deadly; bool canBash2 = canBash; TraverseParms traverseParams = TraverseParms.For(searcherPawn2, maxDanger, TraverseMode.ByPawn, canBash2); float maxDist2 = maxDist; bool validator3(Thing x) => innerValidator((IAttackTarget)x); int searchRegionsMax = (maxDist <= 800f) ? 40 : -1; IAttackTarget attackTarget2 = (IAttackTarget)GenClosest.ClosestThingReachable(position, map, thingReq, peMode, traverseParams, maxDist2, validator3, null, 0, searchRegionsMax, false, RegionType.Set_Passable, false); if (attackTarget2 != null && PawnUtility.ShouldCollideWithPawns(searcherPawn)) { IAttackTarget attackTarget3 = PCF_AttackTargetFinder.FindBestReachableMeleeTarget(innerValidator, searcherPawn, maxDist, canBash); if (attackTarget3 != null) { float lengthHorizontal = (searcherPawn.Position - attackTarget2.Thing.Position).LengthHorizontal; float lengthHorizontal2 = (searcherPawn.Position - attackTarget3.Thing.Position).LengthHorizontal; if (Mathf.Abs(lengthHorizontal - lengthHorizontal2) < 50f) { attackTarget2 = attackTarget3; } } } return(attackTarget2); }
private static List <Pair <IAttackTarget, float> > GetAvailableShootingTargetsByScore(List <IAttackTarget> rawTargets, IAttackTargetSearcher searcher, Verb verb) { AdeptusAttackTargetFinder.availableShootingTargets.Clear(); if (rawTargets.Count == 0) { return(AdeptusAttackTargetFinder.availableShootingTargets); } AdeptusAttackTargetFinder.tmpTargetScores.Clear(); AdeptusAttackTargetFinder.tmpCanShootAtTarget.Clear(); float num = 0f; IAttackTarget attackTarget = null; for (int i = 0; i < rawTargets.Count; i++) { AdeptusAttackTargetFinder.tmpTargetScores.Add(-3.40282347E+38f); AdeptusAttackTargetFinder.tmpCanShootAtTarget.Add(false); if (rawTargets[i] != searcher) { bool flag = AdeptusAttackTargetFinder.CanShootAtFromCurrentPosition(rawTargets[i], searcher, verb); AdeptusAttackTargetFinder.tmpCanShootAtTarget[i] = flag; if (flag) { float shootingTargetScore = AdeptusAttackTargetFinder.GetShootingTargetScore(rawTargets[i], searcher, verb); AdeptusAttackTargetFinder.tmpTargetScores[i] = shootingTargetScore; if (attackTarget == null || shootingTargetScore > num) { attackTarget = rawTargets[i]; num = shootingTargetScore; } } } } if (num < 1f) { if (attackTarget != null) { AdeptusAttackTargetFinder.availableShootingTargets.Add(new Pair <IAttackTarget, float>(attackTarget, 1f)); } } else { float num2 = num - 30f; for (int j = 0; j < rawTargets.Count; j++) { if (rawTargets[j] != searcher) { if (AdeptusAttackTargetFinder.tmpCanShootAtTarget[j]) { float num3 = AdeptusAttackTargetFinder.tmpTargetScores[j]; if (num3 >= num2) { float second = Mathf.InverseLerp(num - 30f, num, num3); AdeptusAttackTargetFinder.availableShootingTargets.Add(new Pair <IAttackTarget, float>(rawTargets[j], second)); } } } } } return(AdeptusAttackTargetFinder.availableShootingTargets); }
private static bool HasRangedAttack(IAttackTargetSearcher t, Verb verb) { return(verb != null && !verb.verbProps.IsMeleeAttack); }
private static float FriendlyFireShootingTargetScoreOffset(IAttackTarget target, IAttackTargetSearcher searcher, Verb verb) { if (verb.verbProps.ai_AvoidFriendlyFireRadius <= 0f) { return(0f); } Map map = target.Thing.Map; IntVec3 position = target.Thing.Position; int num = GenRadial.NumCellsInRadius(verb.verbProps.ai_AvoidFriendlyFireRadius); float num2 = 0f; for (int i = 0; i < num; i++) { IntVec3 intVec = position + GenRadial.RadialPattern[i]; if (intVec.InBounds(map)) { bool flag = true; List <Thing> thingList = intVec.GetThingList(map); for (int j = 0; j < thingList.Count; j++) { if (thingList[j] is IAttackTarget && thingList[j] != target) { if (flag) { if (!GenSight.LineOfSight(position, intVec, map, true, null, 0, 0)) { break; } flag = false; } float num3; if (thingList[j] == searcher) { num3 = 40f; } else if (thingList[j] is Pawn) { num3 = ((!thingList[j].def.race.Animal) ? 18f : 7f); } else { num3 = 10f; } if (searcher.Thing.HostileTo(thingList[j])) { num2 += num3 * 0.6f; } else { num2 -= num3; } } } } } return(Mathf.Min(num2, 0f)); }
private static float FriendlyFireConeTargetScoreOffset(IAttackTarget target, IAttackTargetSearcher searcher, Verb verb) { if (!(searcher.Thing is Pawn pawn)) { return(0f); } if (pawn.RaceProps.intelligence < Intelligence.ToolUser) { return(0f); } if (pawn.RaceProps.IsMechanoid) { return(0f); } if (!(verb is Verb_Shoot verb_Shoot)) { return(0f); } ThingDef defaultProjectile = verb_Shoot.verbProps.defaultProjectile; if (defaultProjectile == null) { return(0f); } if (defaultProjectile.projectile.flyOverhead) { return(0f); } Map map = pawn.Map; ShotReport report = ShotReport.HitReportFor(pawn, verb, (Thing)target); float a = VerbUtility.CalculateAdjustedForcedMiss(verb.verbProps.ForcedMissRadius, report.ShootLine.Dest - report.ShootLine.Source); float radius = Mathf.Max(a, 1.5f); IntVec3 dest2 = report.ShootLine.Dest; IEnumerable <IntVec3> source = from dest in GenRadial.RadialCellsAround(dest2, radius, true) where dest.InBounds(map) select dest; IEnumerable <ShootLine> source2 = from dest in source select new ShootLine(report.ShootLine.Source, dest); IEnumerable <IntVec3> source3 = source2.SelectMany((ShootLine line) => line.Points().Concat(line.Dest).TakeWhile((IntVec3 pos) => pos.CanBeSeenOverFast(map))); IEnumerable <IntVec3> enumerable = source3.Distinct <IntVec3>(); float num = 0f; foreach (IntVec3 c in enumerable) { float num2 = VerbUtility.InterceptChanceFactorFromDistance(report.ShootLine.Source.ToVector3Shifted(), c); if (num2 > 0f) { List <Thing> thingList = c.GetThingList(map); for (int i = 0; i < thingList.Count; i++) { Thing thing = thingList[i]; if (thing is IAttackTarget && thing != target) { float num3; if (thing == searcher) { num3 = 40f; } else if (thing is Pawn) { num3 = ((!thing.def.race.Animal) ? 18f : 7f); } else { num3 = 10f; } num3 *= num2; if (searcher.Thing.HostileTo(thing)) { num3 *= 0.6f; } else { num3 *= -1f; } num += num3; } } } } return(num); }
public static IAttackTarget BestAttackTarget(IAttackTargetSearcher searcher, TargetScanFlags flags, Predicate <Thing> validator = null, float minDist = 0f, float maxDist = 9999f, IntVec3 locus = default(IntVec3), float maxTravelRadiusFromLocus = float.MaxValue, bool canBash = false, bool canTakeTargetsCloserThanEffectiveMinRange = true) { Thing searcherThing = searcher.Thing; Pawn searcherPawn = searcher as Pawn; Verb verb = searcher.CurrentEffectiveVerb; if (verb == null) { Log.Error("BestAttackTarget with " + searcher.ToStringSafe() + " who has no attack verb."); return(null); } bool onlyTargetMachines = verb.IsEMP(); float minDistSquared = 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 (minDistSquared > 0f && (float)(searcherThing.Position - thing.Position).LengthHorizontalSquared < minDistSquared) { return(false); } if (!canTakeTargetsCloserThanEffectiveMinRange) { float num2 = verb.verbProps.EffectiveMinRange(thing, searcherThing); if (num2 > 0f && (float)(searcherThing.Position - thing.Position).LengthHorizontalSquared < num2 * num2) { return(false); } } if (maxTravelRadiusFromLocus < 9999f && (float)(thing.Position - locus).LengthHorizontalSquared > maxLocusDistSquared) { return(false); } if (!searcherThing.HostileTo(thing)) { return(false); } if (validator != null && !validator(thing)) { return(false); } if (searcherPawn != null) { Lord lord = searcherPawn.GetLord(); if (lord != null && !lord.LordJob.ValidateAttackTarget(searcherPawn, thing)) { // Log.Messageage(thing + " lord ValidateAttackTarget: false"); return(false); } } if ((flags & TargetScanFlags.NeedNotUnderThickRoof) != 0) { RoofDef roof = thing.Position.GetRoof(thing.Map); if (roof != null && roof.isThickRoof) { // Log.Messageage(thing + " isThickRoof: false"); return(false); } } if ((flags & TargetScanFlags.NeedLOSToAll) != 0) { if (losValidator != null && (!losValidator(searcherThing.Position) || !losValidator(thing.Position))) { // Log.Messageage(thing + " LOSToAll: false"); return(false); } if (!searcherThing.CanSee(thing, losValidator)) { if (t is Pawn) { if ((flags & TargetScanFlags.NeedLOSToPawns) != 0) { // Log.Messageage(thing + " LOSToPawns: false"); return(false); } } else if ((flags & TargetScanFlags.NeedLOSToNonPawns) != 0) { // Log.Messageage(thing + " LOSToNonPawns: false"); return(false); } } } if (((flags & TargetScanFlags.NeedThreat) != 0 || (flags & TargetScanFlags.NeedAutoTargetable) != 0) && t.ThreatDisabled(searcher)) { // Log.Messageage(thing + " NeedThreat: false"); return(false); } if ((flags & TargetScanFlags.NeedAutoTargetable) != 0 && !IsAutoTargetable(t)) { // Log.Messageage(thing + " NeedAutoTargetable: false"); return(false); } if ((flags & TargetScanFlags.NeedActiveThreat) != 0 && !GenHostility.IsActiveThreatTo(t, searcher.Thing.Faction)) { // Log.Messageage(thing + " NeedActiveThreat: false"); return(false); } Pawn pawn = t as Pawn; if (onlyTargetMachines && pawn != null && pawn.RaceProps.IsFlesh) { // Log.Messageage(thing + " onlyTargetMachines: false"); return(false); } if ((flags & TargetScanFlags.NeedNonBurning) != 0 && thing.IsBurning()) { // Log.Messageage(thing + " NeedNonBurning: false"); return(false); } if (searcherThing.def.race != null && (int)searcherThing.def.race.intelligence >= 2) { CompExplosive compExplosive = thing.TryGetCompFast <CompExplosive>(); if (compExplosive != null && compExplosive.wickStarted) { // Log.Messageage(thing + " wickStarted: false"); return(false); } } if (thing.def.size.x == 1 && thing.def.size.z == 1) { if (thing.Position.Fogged(thing.Map)) { // Log.Messageage(thing + " Fogged: false"); return(false); } } else { bool flag2 = false; foreach (IntVec3 item in thing.OccupiedRect()) { if (!item.Fogged(thing.Map)) { flag2 = true; break; } } if (!flag2) { // Log.Messageage(thing + " Fogged: false"); return(false); } } // Log.Messageage(thing + " valid: true"); return(true); }; if (HasRangedAttack(searcher) && (searcherPawn == null || !searcherPawn.InAggroMentalState)) { // Log.Messageage(searcher + "AttackTargetFinder.HasRangedAttack 0"); tmpTargets.Clear(); // Log.Messageage(searcher + "AttackTargetFinder.HasRangedAttack 1"); tmpTargets.AddRange(searcherThing.Map.attackTargetsCache.GetPotentialTargetsFor(searcher)); // Log.Messageage(searcher + "AttackTargetFinder.HasRangedAttack 2 tmpTargets: " + tmpTargets.Count); if ((flags & TargetScanFlags.NeedReachable) != 0) { Predicate <IAttackTarget> oldValidator2 = innerValidator; innerValidator = ((IAttackTarget t) => oldValidator2(t) && CanReach(searcherThing, t.Thing, canBash)); } // Log.Messageage(searcher + "AttackTargetFinder.HasRangedAttack 3"); bool flag = false; for (int i = 0; i < tmpTargets.Count; i++) { IAttackTarget attackTarget = tmpTargets[i]; if (attackTarget.Thing.Position.InHorDistOf(searcherThing.Position, maxDist) && innerValidator(attackTarget) && CanShootAtFromCurrentPosition(attackTarget, searcher, verb)) { flag = true; break; } } // Log.Messageage(searcher + "AttackTargetFinder.HasRangedAttack 4 "); IAttackTarget attackTarget2; if (flag) { tmpTargets.RemoveAll((IAttackTarget x) => !x.Thing.Position.InHorDistOf(searcherThing.Position, maxDist) || !innerValidator(x)); attackTarget2 = GetRandomShootingTargetByScore(tmpTargets, searcher, verb); } else { attackTarget2 = (IAttackTarget)GenClosest.ClosestThing_Global(validator: ((flags & TargetScanFlags.NeedReachableIfCantHitFromMyPos) == 0 || (flags & TargetScanFlags.NeedReachable) != 0) ? ((Predicate <Thing>)((Thing t) => innerValidator((IAttackTarget)t))) : ((Predicate <Thing>)((Thing t) => innerValidator((IAttackTarget)t) && (CanReach(searcherThing, t, canBash) || CanShootAtFromCurrentPosition((IAttackTarget)t, searcher, verb)))), center: searcherThing.Position, searchSet: tmpTargets, maxDistance: maxDist); } // Log.Messageage(searcher + "AttackTargetFinder.HasRangedAttack 5"); tmpTargets.Clear(); // Log.Messageage(searcher + "AttackTargetFinder.HasRangedAttack tgt found: " + (attackTarget2 != null).ToString()); return(attackTarget2); } // Log.Messageage(searcher + "AttackTargetFinder.HasRangedAttack no ranged attack found"); if (searcherPawn != null && searcherPawn.mindState.duty != null && searcherPawn.mindState.duty.radius > 0f && !searcherPawn.InMentalState) { Predicate <IAttackTarget> oldValidator = innerValidator; innerValidator = ((IAttackTarget t) => oldValidator(t) && t.Thing.Position.InHorDistOf(searcherPawn.mindState.duty.focus.Cell, searcherPawn.mindState.duty.radius)); } IAttackTarget attackTarget3 = (IAttackTarget)GenClosest.ClosestThingReachable(searcherThing.Position, searcherThing.Map, ThingRequest.ForGroup(ThingRequestGroup.AttackTarget), PathEndMode.Touch, TraverseParms.For(searcherPawn, Danger.Deadly, TraverseMode.ByPawn, canBash), maxDist, (Thing x) => innerValidator((IAttackTarget)x), null, 0, (maxDist > 800f) ? (-1) : 40); if (attackTarget3 != null && PawnUtility.ShouldCollideWithPawns(searcherPawn)) { IAttackTarget attackTarget4 = FindBestReachableMeleeTarget(innerValidator, searcherPawn, maxDist, canBash); if (attackTarget4 != null) { float lengthHorizontal = (searcherPawn.Position - attackTarget3.Thing.Position).LengthHorizontal; float lengthHorizontal2 = (searcherPawn.Position - attackTarget4.Thing.Position).LengthHorizontal; if (Mathf.Abs(lengthHorizontal - lengthHorizontal2) < 50f) { attackTarget3 = attackTarget4; } } } return(attackTarget3); }
private static List <Pair <IAttackTarget, float> > GetAvailableShootingTargetsByScore( List <IAttackTarget> rawTargets, IAttackTargetSearcher searcher, Verb verb) { List <Pair <IAttackTarget, float> > availableShootingTargets = new List <Pair <IAttackTarget, float> >(); //AttackTargetFinder.availableShootingTargets.Clear(); if (rawTargets.Count == 0) { return(availableShootingTargets); } //AttackTargetFinder.tmpTargetScores.Clear(); List <float> tmpTargetScores = new List <float>(); //AttackTargetFinder.tmpCanShootAtTarget.Clear(); List <bool> tmpCanShootAtTarget = new List <bool>(); float b = 0.0f; IAttackTarget first = (IAttackTarget)null; for (int index = 0; index < rawTargets.Count; ++index) { tmpTargetScores.Add(float.MinValue); tmpCanShootAtTarget.Add(false); if (rawTargets[index] != searcher) { bool flag = CanShootAtFromCurrentPosition(rawTargets[index], searcher, verb); tmpCanShootAtTarget[index] = flag; if (flag) { float shootingTargetScore = GetShootingTargetScore(rawTargets[index], searcher, verb); tmpTargetScores[index] = shootingTargetScore; if (first == null || (double)shootingTargetScore > (double)b) { first = rawTargets[index]; b = shootingTargetScore; } } } } if ((double)b < 1.0) { if (first != null) { availableShootingTargets.Add(new Pair <IAttackTarget, float>(first, 1f)); } } else { float num = b - 30f; for (int index = 0; index < rawTargets.Count; ++index) { if (rawTargets[index] != searcher && tmpCanShootAtTarget[index]) { float tmpTargetScore = tmpTargetScores[index]; if ((double)tmpTargetScore >= (double)num) { float second = Mathf.InverseLerp(b - 30f, b, tmpTargetScore); availableShootingTargets.Add(new Pair <IAttackTarget, float>(rawTargets[index], second)); } } } } return(availableShootingTargets); }
private static IAttackTarget GetRandomShootingTargetByScore(List <IAttackTarget> targets, IAttackTargetSearcher searcher, Verb verb) { if (GetAvailableShootingTargetsByScore(targets, searcher, verb).TryRandomElementByWeight((Pair <IAttackTarget, float> x) => x.Second, out Pair <IAttackTarget, float> result)) { return(result.First); } return(null); }
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); }