public static void DebugDrawAttackTargetScores_Update() { IAttackTargetSearcher attackTargetSearcher = Find.Selector.SingleSelectedThing as IAttackTargetSearcher; if (attackTargetSearcher == null) { return; } if (attackTargetSearcher.Thing.Map != Find.CurrentMap) { return; } Verb currentEffectiveVerb = attackTargetSearcher.CurrentEffectiveVerb; if (currentEffectiveVerb == null) { return; } AttackTargetFinder.tmpTargets.Clear(); List <Thing> list = attackTargetSearcher.Thing.Map.listerThings.ThingsInGroup(ThingRequestGroup.AttackTarget); for (int i = 0; i < list.Count; i++) { AttackTargetFinder.tmpTargets.Add((IAttackTarget)list[i]); } List <Pair <IAttackTarget, float> > availableShootingTargetsByScore = AttackTargetFinder.GetAvailableShootingTargetsByScore(AttackTargetFinder.tmpTargets, attackTargetSearcher, currentEffectiveVerb); for (int j = 0; j < availableShootingTargetsByScore.Count; j++) { GenDraw.DrawLineBetween(attackTargetSearcher.Thing.DrawPos, availableShootingTargetsByScore[j].First.Thing.DrawPos); } }
private static List <Pair <IAttackTarget, float> > GetAvailableShootingTargetsByScore(List <IAttackTarget> rawTargets, IAttackTargetSearcher searcher, Verb verb) { AttackTargetFinder.availableShootingTargets.Clear(); if (rawTargets.Count == 0) { return(AttackTargetFinder.availableShootingTargets); } AttackTargetFinder.tmpTargetScores.Clear(); AttackTargetFinder.tmpCanShootAtTarget.Clear(); float num = 0f; IAttackTarget attackTarget = null; for (int i = 0; i < rawTargets.Count; i++) { AttackTargetFinder.tmpTargetScores.Add(float.MinValue); AttackTargetFinder.tmpCanShootAtTarget.Add(false); if (rawTargets[i] != searcher) { bool flag = AttackTargetFinder.CanShootAtFromCurrentPosition(rawTargets[i], searcher, verb); AttackTargetFinder.tmpCanShootAtTarget[i] = flag; if (flag) { float shootingTargetScore = AttackTargetFinder.GetShootingTargetScore(rawTargets[i], searcher, verb); AttackTargetFinder.tmpTargetScores[i] = shootingTargetScore; if (attackTarget == null || shootingTargetScore > num) { attackTarget = rawTargets[i]; num = shootingTargetScore; } } } } if (num < 1f) { if (attackTarget != null) { AttackTargetFinder.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 (AttackTargetFinder.tmpCanShootAtTarget[j]) { float num3 = AttackTargetFinder.tmpTargetScores[j]; if (num3 >= num2) { float second = Mathf.InverseLerp(num - 30f, num, num3); AttackTargetFinder.availableShootingTargets.Add(new Pair <IAttackTarget, float>(rawTargets[j], second)); } } } } } return(AttackTargetFinder.availableShootingTargets); }
private static IAttackTarget GetRandomShootingTargetByScore(List <IAttackTarget> targets, IAttackTargetSearcher searcher, Verb verb) { Pair <IAttackTarget, float> pair; if (AttackTargetFinder.GetAvailableShootingTargetsByScore(targets, searcher, verb).TryRandomElementByWeight((Pair <IAttackTarget, float> x) => x.Second, out pair)) { return(pair.First); } return(null); }
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 BestShootTargetFromCurrentPosition(IAttackTargetSearcher searcher, TargetScanFlags flags, Predicate <Thing> validator = null, float minDistance = 0f, float maxDistance = 9999f) { Verb currentEffectiveVerb = searcher.CurrentEffectiveVerb; if (currentEffectiveVerb == null) { Log.Error("BestShootTargetFromCurrentPosition with " + searcher.ToStringSafe <IAttackTargetSearcher>() + " who has no attack verb.", false); return(null); } return(AttackTargetFinder.BestAttackTarget(searcher, flags, validator, Mathf.Max(minDistance, currentEffectiveVerb.verbProps.minRange), Mathf.Min(maxDistance, currentEffectiveVerb.verbProps.range), default(IntVec3), float.MaxValue, false, false)); }
public static void DebugDrawAttackTargetScores_OnGUI() { IAttackTargetSearcher attackTargetSearcher = Find.Selector.SingleSelectedThing as IAttackTargetSearcher; if (attackTargetSearcher == null) { return; } if (attackTargetSearcher.Thing.Map != Find.CurrentMap) { return; } Verb currentEffectiveVerb = attackTargetSearcher.CurrentEffectiveVerb; if (currentEffectiveVerb == null) { return; } List <Thing> list = attackTargetSearcher.Thing.Map.listerThings.ThingsInGroup(ThingRequestGroup.AttackTarget); Text.Anchor = TextAnchor.MiddleCenter; Text.Font = GameFont.Tiny; for (int i = 0; i < list.Count; i++) { Thing thing = list[i]; if (thing != attackTargetSearcher) { string text; Color red; if (!AttackTargetFinder.CanShootAtFromCurrentPosition((IAttackTarget)thing, attackTargetSearcher, currentEffectiveVerb)) { text = "out of range"; red = Color.red; } else { text = AttackTargetFinder.GetShootingTargetScore((IAttackTarget)thing, attackTargetSearcher, currentEffectiveVerb).ToString("F0"); red = new Color(0.25f, 1f, 0.25f); } Vector2 screenPos = thing.DrawPos.MapToUIPosition(); GenMapUI.DrawThingLabel(screenPos, text, red); } } Text.Anchor = TextAnchor.UpperLeft; Text.Font = GameFont.Small; }
private static float GetShootingTargetScore(IAttackTarget target, IAttackTargetSearcher searcher, Verb verb) { float num = 60f; num -= Mathf.Min((target.Thing.Position - searcher.Thing.Position).LengthHorizontal, 40f); if (target.TargetCurrentlyAimingAt == searcher.Thing) { num += 10f; } if (searcher.LastAttackedTarget == target.Thing && Find.TickManager.TicksGame - searcher.LastAttackTargetTick <= 300) { num += 40f; } num -= CoverUtility.CalculateOverallBlockChance(target.Thing.Position, searcher.Thing.Position, searcher.Thing.Map) * 10f; Pawn pawn = target as Pawn; if (pawn != null && pawn.RaceProps.Animal && pawn.Faction != null && !pawn.IsFighting()) { num -= 50f; } return(num + AttackTargetFinder.FriendlyFireShootingTargetScoreOffset(target, searcher, verb)); }
// Token: 0x0600004A RID: 74 RVA: 0x00003EE8 File Offset: 0x000020E8 private void CheckForAutoAttack() { bool downed = this.pawn.Downed; if (!downed) { bool fullBodyBusy = this.pawn.stances.FullBodyBusy; if (!fullBodyBusy) { bool flag = this.pawn.jobs.jobQueue != null; if (!flag) { bool flag2 = this.pawn.Faction != null && this.pawn.jobs.curJob.def == WPJobDefOf.ArtyWaitCombat; if (flag2) { Verb currentEffectiveVerb = this.pawn.CurrentEffectiveVerb; bool flag3 = currentEffectiveVerb != null && !currentEffectiveVerb.verbProps.IsMeleeAttack; if (flag3) { TargetScanFlags targetScanFlags = TargetScanFlags.None; bool flag4 = currentEffectiveVerb.IsIncendiary(); if (flag4) { targetScanFlags |= TargetScanFlags.NeedNonBurning; } Thing thing = (Thing)AttackTargetFinder.BestShootTargetFromCurrentPosition(this.pawn, targetScanFlags, null, 0f, 9999f); bool flag5 = thing != null; if (flag5) { this.pawn.TryStartAttack(thing); this.collideWithPawns = true; } } } } } } }
private void CheckForAutoAttack() { if (this.pawn.Downed) { return; } if (this.pawn.stances.FullBodyBusy) { return; } this.collideWithPawns = false; bool flag = this.pawn.story == null || !this.pawn.story.WorkTagIsDisabled(WorkTags.Violent); bool flag2 = this.pawn.RaceProps.ToolUser && this.pawn.Faction == Faction.OfPlayer && !this.pawn.story.WorkTagIsDisabled(WorkTags.Firefighting); if (flag || flag2) { Fire fire = null; for (int i = 0; i < 9; i++) { IntVec3 c = this.pawn.Position + GenAdj.AdjacentCellsAndInside[i]; if (c.InBounds(this.pawn.Map)) { List <Thing> thingList = c.GetThingList(base.Map); for (int j = 0; j < thingList.Count; j++) { if (flag) { Pawn pawn = thingList[j] as Pawn; if (pawn != null && !pawn.Downed && this.pawn.HostileTo(pawn)) { this.pawn.meleeVerbs.TryMeleeAttack(pawn, null, false); this.collideWithPawns = true; return; } } if (flag2) { Fire fire2 = thingList[j] as Fire; if (fire2 != null && (fire == null || fire2.fireSize < fire.fireSize || i == 8) && (fire2.parent == null || fire2.parent != this.pawn)) { fire = fire2; } } } } } if (fire != null && (!this.pawn.InMentalState || this.pawn.MentalState.def.allowBeatfire)) { this.pawn.natives.TryBeatFire(fire); return; } if (flag && this.pawn.Faction != null && this.job.def == JobDefOf.Wait_Combat && (this.pawn.drafter == null || this.pawn.drafter.FireAtWill)) { Verb currentEffectiveVerb = this.pawn.CurrentEffectiveVerb; if (currentEffectiveVerb != null && !currentEffectiveVerb.verbProps.IsMeleeAttack) { TargetScanFlags targetScanFlags = TargetScanFlags.NeedLOSToPawns | TargetScanFlags.NeedLOSToNonPawns | TargetScanFlags.NeedThreat; if (currentEffectiveVerb.IsIncendiary()) { targetScanFlags |= TargetScanFlags.NeedNonBurning; } Thing thing = (Thing)AttackTargetFinder.BestShootTargetFromCurrentPosition(this.pawn, targetScanFlags, null, 0f, 9999f); if (thing != null) { this.pawn.TryStartAttack(thing); this.collideWithPawns = true; return; } } } } }
internal bool <> m__3(Thing t) { return(this.innerValidator((IAttackTarget)t) && (AttackTargetFinder.CanReach(this.searcherThing, t, this.canBash) || AttackTargetFinder.CanShootAtFromCurrentPosition((IAttackTarget)t, this.searcher, this.verb))); }
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, 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); 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); } 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.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)) { flag2 = true; break; } iterator.MoveNext(); } if (!flag2) { return(false); } } return(true); }; if (AttackTargetFinder.HasRangedAttack(searcher)) { AttackTargetFinder.tmpTargets.Clear(); AttackTargetFinder.tmpTargets.AddRange(searcherThing.Map.attackTargetsCache.GetPotentialTargetsFor(searcher)); if ((byte)(flags & TargetScanFlags.NeedReachable) != 0) { Predicate <IAttackTarget> oldValidator = innerValidator; innerValidator = ((IAttackTarget t) => oldValidator(t) && AttackTargetFinder.CanReach(searcherThing, t.Thing, canBash)); } bool flag = false; 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; if ((byte)(flags & TargetScanFlags.NeedReachableIfCantHitFromMyPos) != 0 && (byte)(flags & TargetScanFlags.NeedReachable) == 0) { validator2 = ((Thing t) => innerValidator((IAttackTarget)t) && (AttackTargetFinder.CanReach(searcherThing, t, canBash) || AttackTargetFinder.CanShootAtFromCurrentPosition((IAttackTarget)t, searcher, verb))); } else { validator2 = ((Thing t) => innerValidator((IAttackTarget)t)); } 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 > 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; Predicate <Thing> 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 = 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 void CheckForAutoAttack() { if (pawn.Downed) { return; } //Don't auto-attack while warming up etc if (pawn.stances.FullBodyBusy) { return; } collideWithPawns = false; //Note: While bursting, there seems to be a gap where the pawn becomes mobile? bool canDoViolence = pawn.story == null || !pawn.story.WorkTagIsDisabled(WorkTags.Violent); bool shouldFightFires = pawn.RaceProps.ToolUser && pawn.Faction == Faction.OfPlayer && !pawn.story.WorkTagIsDisabled(WorkTags.Firefighting); if (canDoViolence || shouldFightFires) { //Melee attack adjacent enemy pawns //Barring that, put out fires Fire targetFire = null; for (int i = 0; i < 9; i++) { IntVec3 neigh = pawn.Position + GenAdj.AdjacentCellsAndInside[i]; if (!neigh.InBounds(pawn.Map)) { continue; } var things = neigh.GetThingList(Map); for (int j = 0; j < things.Count; j++) { if (canDoViolence) { //We just hit the first pawn we see (north first) Pawn otherPawn = things[j] as Pawn; if (otherPawn != null && !otherPawn.Downed && pawn.HostileTo(otherPawn)) { pawn.meleeVerbs.TryMeleeAttack(otherPawn); collideWithPawns = true; return; } } //Prioritize the fire we're standing on. //If there isn't one, prioritize the smallest fire //This algorithm assumes that the inside cell is last if (shouldFightFires) { Fire fire = things[j] as Fire; if (fire != null && (targetFire == null || fire.fireSize < targetFire.fireSize || i == 8) && (fire.parent == null || fire.parent != pawn)) { targetFire = fire; } } } } //We didn't do a melee attack, so see if we found a fire to beat if (targetFire != null && (!pawn.InMentalState || pawn.MentalState.def.allowBeatfire)) { pawn.natives.TryBeatFire(targetFire); return; } //Shoot at the closest enemy in range if (canDoViolence && pawn.Faction != null && job.def == JobDefOf.Wait_Combat && (pawn.drafter == null || pawn.drafter.FireAtWill)) { var attackVerb = pawn.CurrentEffectiveVerb; if (attackVerb != null && !attackVerb.verbProps.IsMeleeAttack) { //We increase the range because we can hit targets slightly outside range by shooting at their ShootableSquares //We could just put the range at int.MaxValue but this is slightly more optimized so whatever var flags = TargetScanFlags.NeedLOSToAll | TargetScanFlags.NeedThreat; if (attackVerb.IsIncendiary()) { flags |= TargetScanFlags.NeedNonBurning; } var curTarg = (Thing)AttackTargetFinder.BestShootTargetFromCurrentPosition(pawn, flags); if (curTarg != null) { pawn.TryStartAttack(curTarg); collideWithPawns = true; return; } } } } }
public static IAttackTarget BestShootTargetFromCurrentPosition(IAttackTargetSearcher searcher, Predicate <Thing> validator, float maxDistance, float minDistance, TargetScanFlags flags) { return(AttackTargetFinder.BestAttackTarget(searcher, flags, validator, minDistance, maxDistance, default(IntVec3), 3.40282347E+38f, false)); }
private void CheckForAutoAttack() { if (!base.pawn.Downed && !base.pawn.stances.FullBodyBusy) { bool flag = base.pawn.story == null || !base.pawn.story.WorkTagIsDisabled(WorkTags.Violent); bool flag2 = base.pawn.RaceProps.ToolUser && base.pawn.Faction == Faction.OfPlayer && !base.pawn.story.WorkTagIsDisabled(WorkTags.Firefighting); if (!flag && !flag2) { return; } Fire fire = null; for (int i = 0; i < 9; i++) { IntVec3 c = base.pawn.Position + GenAdj.AdjacentCellsAndInside[i]; if (c.InBounds(base.pawn.Map)) { List <Thing> thingList = c.GetThingList(base.Map); for (int j = 0; j < thingList.Count; j++) { if (flag) { Pawn pawn = thingList[j] as Pawn; if (pawn != null && !pawn.Downed && base.pawn.HostileTo(pawn)) { base.pawn.meleeVerbs.TryMeleeAttack(pawn, null, false); return; } } if (flag2) { Fire fire2 = thingList[j] as Fire; if (fire2 != null && (fire == null || fire2.fireSize < fire.fireSize || i == 8) && (fire2.parent == null || fire2.parent != base.pawn)) { fire = fire2; } } } } } if (fire != null && (!base.pawn.InMentalState || base.pawn.MentalState.def.allowBeatfire)) { base.pawn.natives.TryBeatFire(fire); } else if (flag && base.pawn.Faction != null && base.job.def == JobDefOf.WaitCombat) { if (base.pawn.drafter != null && !base.pawn.drafter.FireAtWill) { return; } bool allowManualCastWeapons = !base.pawn.IsColonist; Verb verb = base.pawn.TryGetAttackVerb(allowManualCastWeapons); if (verb != null && !verb.verbProps.MeleeRange) { TargetScanFlags targetScanFlags = TargetScanFlags.NeedLOSToPawns | TargetScanFlags.NeedLOSToNonPawns | TargetScanFlags.NeedThreat; if (verb.IsIncendiary()) { targetScanFlags |= TargetScanFlags.NeedNonBurning; } Thing thing = (Thing)AttackTargetFinder.BestShootTargetFromCurrentPosition(base.pawn, null, verb.verbProps.range, verb.verbProps.minRange, targetScanFlags); if (thing != null) { base.pawn.TryStartAttack(thing); } } } } }
private void CheckForAutoAttack() { if (base.pawn.Downed || base.pawn.stances.FullBodyBusy) { return; } collideWithPawns = false; bool flag = !base.pawn.WorkTagIsDisabled(WorkTags.Violent); bool flag2 = base.pawn.RaceProps.ToolUser && base.pawn.Faction == Faction.OfPlayer && !base.pawn.WorkTagIsDisabled(WorkTags.Firefighting); if (!(flag || flag2)) { return; } Fire fire = null; for (int i = 0; i < 9; i++) { IntVec3 c = base.pawn.Position + GenAdj.AdjacentCellsAndInside[i]; if (!c.InBounds(base.pawn.Map)) { continue; } List <Thing> thingList = c.GetThingList(base.Map); for (int j = 0; j < thingList.Count; j++) { if (flag) { Pawn pawn = thingList[j] as Pawn; if (pawn != null && !pawn.Downed && base.pawn.HostileTo(pawn) && GenHostility.IsActiveThreatTo(pawn, base.pawn.Faction)) { base.pawn.meleeVerbs.TryMeleeAttack(pawn); collideWithPawns = true; return; } } if (flag2) { Fire fire2 = thingList[j] as Fire; if (fire2 != null && (fire == null || fire2.fireSize < fire.fireSize || i == 8) && (fire2.parent == null || fire2.parent != base.pawn)) { fire = fire2; } } } } if (fire != null && (!base.pawn.InMentalState || base.pawn.MentalState.def.allowBeatfire)) { base.pawn.natives.TryBeatFire(fire); } else { if (!flag || !job.canUseRangedWeapon || base.pawn.Faction == null || job.def != JobDefOf.Wait_Combat || (base.pawn.drafter != null && !base.pawn.drafter.FireAtWill)) { return; } Verb currentEffectiveVerb = base.pawn.CurrentEffectiveVerb; if (currentEffectiveVerb != null && !currentEffectiveVerb.verbProps.IsMeleeAttack) { TargetScanFlags targetScanFlags = TargetScanFlags.NeedLOSToAll | TargetScanFlags.NeedThreat | TargetScanFlags.NeedAutoTargetable; if (currentEffectiveVerb.IsIncendiary()) { targetScanFlags |= TargetScanFlags.NeedNonBurning; } Thing thing = (Thing)AttackTargetFinder.BestShootTargetFromCurrentPosition(base.pawn, targetScanFlags); if (thing != null) { base.pawn.TryStartAttack(thing); collideWithPawns = true; } } } }