static void Postfix(CompExplosive __instance) { if (__instance is CompExplosiveCustom custom) { custom.OnPostDetonated(); } }
public static void ThingDestroy(Thing __instance, DestroyMode mode = DestroyMode.Vanish) { if (!Thing.allowDestroyNonDestroyable && !__instance.def.destroyable) { Log.Error("Tried to destroy non-destroyable thing " + __instance); return; } if (__instance.Destroyed) { Log.Error("Tried to destroy already-destroyed thing " + __instance); return; } bool spawned = __instance.Spawned; Map map = __instance.Map; if (__instance.Spawned) { __instance.DeSpawn(mode); } mapIndexOrState(__instance) = -2; if (__instance.def.DiscardOnDestroyed) { __instance.Discard(); } CompExplosive compExplosive = __instance.TryGetComp <CompExplosive>(); if (spawned) { List <Thing> list = (compExplosive != null) ? new List <Thing>() : null; GenLeaving.DoLeavingsFor(__instance, map, mode, list); compExplosive?.AddThingsIgnoredByExplosion(list); } if (__instance.holdingOwner != null) { __instance.holdingOwner.Notify_ContainedItemDestroyed(__instance); } RemoveAllReservationsAndDesignationsOnThis(__instance); if (!(__instance is Pawn)) { __instance.stackCount = 0; } if (mode != DestroyMode.QuestLogic) { QuestUtility.SendQuestTargetSignals(__instance.questTags, "Destroyed", __instance.Named("SUBJECT")); } if (mode == DestroyMode.KillFinalize) { QuestUtility.SendQuestTargetSignals(__instance.questTags, "Killed", __instance.Named("SUBJECT")); } }
// ===================== Spawn setup ===================== public override void SpawnSetup() { base.SpawnSetup(); this.powerOutputDuringCharge = this.powerComp.PowerOutput; this.explosiveComp = GetComp<CompExplosive>(); skywrathTexture = MaterialPool.MatFrom(this.def.graphicData.texPath, ShaderDatabase.Transparent); this.areaOfEffectRadius = this.def.building.turretGunDef.Verbs[0].projectileDef.projectile.explosionRadius; }
// ===================== Spawn setup ===================== public override void SpawnSetup() { base.SpawnSetup(); this.powerOutputDuringCharge = this.powerComp.PowerOutput; this.explosiveComp = GetComp <CompExplosive>(); skywrathTexture = MaterialPool.MatFrom(this.def.graphicData.texPath, ShaderDatabase.Transparent); this.areaOfEffectRadius = this.def.building.turretGunDef.Verbs[0].projectileDef.projectile.explosionRadius; }
public virtual void Destroy(DestroyMode mode = DestroyMode.Vanish) { if (!allowDestroyNonDestroyable && !def.destroyable) { Log.Error("Tried to destroy non-destroyable thing " + this); return; } if (Destroyed) { Log.Error("Tried to destroy already-destroyed thing " + this); return; } bool spawned = Spawned; Map map = Map; if (Spawned) { DeSpawn(mode); } mapIndexOrState = -2; if (def.DiscardOnDestroyed) { Discard(); } CompExplosive compExplosive = this.TryGetComp <CompExplosive>(); if (spawned) { List <Thing> list = ((compExplosive != null) ? new List <Thing>() : null); GenLeaving.DoLeavingsFor(this, map, mode, list); compExplosive?.AddThingsIgnoredByExplosion(list); } if (holdingOwner != null) { holdingOwner.Notify_ContainedItemDestroyed(this); } RemoveAllReservationsAndDesignationsOnThis(); if (!(this is Pawn)) { stackCount = 0; } if (mode != DestroyMode.QuestLogic) { QuestUtility.SendQuestTargetSignals(questTags, "Destroyed", this.Named("SUBJECT")); } if (mode == DestroyMode.KillFinalize) { QuestUtility.SendQuestTargetSignals(questTags, "Killed", this.Named("SUBJECT")); } }
public override void DoEffect(TargetInfo target, Thing caster) { CompBreakdownable breakdownable = target.Thing.TryGetComp <CompBreakdownable>(); if (breakdownable != null) { breakdownable.DoBreakdown(); } CompExplosive explosive = target.Thing.TryGetComp <CompExplosive>(); if (explosive != null) { explosive.StartWick(); } }
public FallingBomb(Thing reference, CompExplosive comp, Map map, string texPathShadow) { this.def = reference.def; this.projectile = def.projectileWhenLoaded.projectile; this.thingIDNumber = reference.thingIDNumber; this.map = map; this.factionInt = reference.Faction; this.graphicInt = reference.DefaultGraphic; this.hitPointsInt = reference.HitPoints; props = reference.TryGetComp <CompExplosive>().Props; if (projectile?.explosionRadius != null) { explosionRadius = def.projectileWhenLoaded.projectile.explosionRadius; } else { explosionRadius = comp.ExplosiveRadius(); } this.texPathShadow = texPathShadow; }
public virtual void Destroy(DestroyMode mode = DestroyMode.Vanish) { if (!Thing.allowDestroyNonDestroyable && !this.def.destroyable) { Log.Error("Tried to destroy non-destroyable thing " + this); return; } if (this.Destroyed) { Log.Error("Tried to destroy already-destroyed thing " + this); return; } bool spawned = this.Spawned; Map map = this.Map; if (this.Spawned) { this.DeSpawn(); } this.mapIndexOrState = -2; if (this.def.DiscardOnDestroyed) { this.Discard(false); } CompExplosive compExplosive = this.TryGetComp <CompExplosive>(); bool flag = compExplosive != null && compExplosive.destroyedThroughDetonation; if (spawned && !flag) { GenLeaving.DoLeavingsFor(this, map, mode); } if (this.holdingOwner != null) { this.holdingOwner.Notify_ContainedItemDestroyed(this); } this.RemoveAllReservationsAndDesignationsOnThis(); if (!(this is Pawn)) { this.stackCount = 0; } }
// TODO: throw motes when successfully subverting public override void DoEffect(TargetInfo target, Thing caster) { // make turrets join your team if (target.Thing is Building_Turret tur && tur.def.CanHaveFaction) { tur.SetFactionDirect(caster.Faction); Log.Message("turret subverted! New faction is " + tur.Faction + "."); } // unlock autodoors if (target.Thing is Building_Door door && door.def.CanHaveFaction && door.TryGetComp <CompPower>() != null) { door.SetFactionDirect(caster.Faction); } if (target.Thing is Pawn targetPawn) { // code biocoded weapons and apparel to the caster // TODO: check to make sure pawn has biocoded gear if (caster is Pawn casterPawn) { SubvertBiocodedGear(targetPawn, casterPawn); } // if pawn is wearing shield belt, set class to custom inverted version if possible // convert mechanoids to your team // TODO: make this a chance instead of guaranteed, based on the mechanoid's health and max HP/combat strength if (targetPawn.def.race.FleshType == FleshTypeDefOf.Mechanoid) { targetPawn.SetFactionDirect(caster.Faction); } } CompExplosive explosive = target.Thing.TryGetComp <CompExplosive>(); if (explosive != null) { explosive.parent.SetFactionDirect(caster.Faction); } }
internal bool <> m__1(IAttackTarget t) { Thing thing = t.Thing; if (t == this.searcher) { return(false); } if (this.minDistSquared > 0f && (float)(this.searcherThing.Position - thing.Position).LengthHorizontalSquared < this.minDistSquared) { return(false); } if (!this.canTakeTargetsCloserThanEffectiveMinRange) { float num = this.verb.verbProps.EffectiveMinRange(thing, this.searcherThing); if (num > 0f && (float)(this.searcherThing.Position - thing.Position).LengthHorizontalSquared < num * num) { return(false); } } if (this.maxTravelRadiusFromLocus < 9999f && (float)(thing.Position - this.locus).LengthHorizontalSquared > this.maxLocusDistSquared) { return(false); } if (!this.searcherThing.HostileTo(thing)) { return(false); } if (this.validator != null && !this.validator(thing)) { return(false); } if (this.searcherPawn != null) { Lord lord = this.searcherPawn.GetLord(); if (lord != null && !lord.LordJob.ValidateAttackTarget(this.searcherPawn, thing)) { return(false); } } if ((byte)(this.flags & TargetScanFlags.NeedLOSToAll) != 0 && !this.searcherThing.CanSee(thing, this.losValidator)) { if (t is Pawn) { if ((byte)(this.flags & TargetScanFlags.NeedLOSToPawns) != 0) { return(false); } } else if ((byte)(this.flags & TargetScanFlags.NeedLOSToNonPawns) != 0) { return(false); } } if ((byte)(this.flags & TargetScanFlags.NeedThreat) != 0 && t.ThreatDisabled(this.searcher)) { return(false); } Pawn pawn = t as Pawn; if (this.onlyTargetMachines && pawn != null && pawn.RaceProps.IsFlesh) { return(false); } if ((byte)(this.flags & TargetScanFlags.NeedNonBurning) != 0 && thing.IsBurning()) { return(false); } if (this.searcherThing.def.race != null && this.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 flag = false; CellRect.CellRectIterator iterator = thing.OccupiedRect().GetIterator(); while (!iterator.Done()) { if (!iterator.Current.Fogged(thing.Map)) { flag = true; break; } iterator.MoveNext(); } if (!flag) { return(false); } } return(true); }
// Token: 0x060000F0 RID: 240 RVA: 0x00008874 File Offset: 0x00006A74 public static void Destroy_Prefix(Thing __instance, DestroyMode mode = DestroyMode.Vanish) { bool flag = !Thing.allowDestroyNonDestroyable && !__instance.def.destroyable; if (!flag) { bool destroyed = __instance.Destroyed; if (!destroyed) { bool spawned = __instance.Spawned; Map map = __instance.Map; bool spawned2 = __instance.Spawned; if (spawned2) { __instance.DeSpawn(mode); } sbyte value = Traverse.Create(typeof(Thing)).Field("mapIndexOrState").GetValue <sbyte>(); bool discardOnDestroyed = __instance.def.DiscardOnDestroyed; if (discardOnDestroyed) { __instance.Discard(false); } CompExplosive compExplosive = __instance.TryGetComp <CompExplosive>(); bool flag2 = compExplosive != null && compExplosive.destroyedThroughDetonation; bool flag3 = spawned && !flag2; if (flag3) { GenLeaving.DoLeavingsFor(__instance, map, mode, null); } bool flag4 = __instance.holdingOwner != null; if (flag4) { __instance.holdingOwner.Notify_ContainedItemDestroyed(__instance); } List <Map> maps = Find.Maps; for (int i = 0; i < maps.Count; i++) { bool flag5 = __instance.def.category == ThingCategory.Mote; if (flag5) { return; } bool flag6 = __instance.def.category != ThingCategory.Mote; if (flag6) { maps[i].reservationManager.ReleaseAllForTarget(__instance); maps[i].physicalInteractionReservationManager.ReleaseAllForTarget(__instance); IAttackTarget attackTarget = __instance as IAttackTarget; bool flag7 = attackTarget != null; if (flag7) { maps[i].attackTargetReservationManager.ReleaseAllForTarget(attackTarget); } maps[i].designationManager.RemoveAllDesignationsOn(__instance, false); } } bool flag8 = !(__instance is Pawn); if (flag8) { __instance.stackCount = 0; } } } }
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.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 (ARA_AttackTargetFinder.HasRangedAttack(searcher)) { //Log.Warning("Finder: Range detected. Verb is " + verb); //Log.Warning("Finder: Pawn " + searcherPawn.Faction); ARA_AttackTargetFinder.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) { ARA_AttackTargetFinder.tmpTargets.Add(iTarget); } if ((byte)(flags & TargetScanFlags.NeedReachable) != 0) { Predicate <IAttackTarget> oldValidator = innerValidator; innerValidator = ((IAttackTarget t) => oldValidator(t) && ARA_AttackTargetFinder.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 < ARA_AttackTargetFinder.tmpTargets.Count; i++) { IAttackTarget attackTarget = ARA_AttackTargetFinder.tmpTargets[i]; if (attackTarget.Thing.Position.InHorDistOf(searcherThing.Position, maxDist) && innerValidator(attackTarget) && ARA_AttackTargetFinder.CanShootAtFromCurrentPosition(attackTarget, searcher, verb)) { //Log.Warning("Finder: flag is true"); flag = true; break; } } } IAttackTarget result; if (flag) { //Log.Warning("Finder: FlagTrue result"); ARA_AttackTargetFinder.tmpTargets.RemoveAll((IAttackTarget x) => !x.Thing.Position.InHorDistOf(searcherThing.Position, maxDist) || !innerValidator(x)); //Log.Warning("Finder: Target Avaliable : " + ARA_AttackTargetFinder.tmpTargets.Count); result = ARA_AttackTargetFinder.GetRandomShootingTargetByScore(ARA_AttackTargetFinder.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) && (ARA_AttackTargetFinder.CanReach(searcherThing, t, canBash) || ARA_AttackTargetFinder.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, ARA_AttackTargetFinder.tmpTargets, maxDist, validator2, null); } ARA_AttackTargetFinder.tmpTargets.Clear(); //Log.Warning("Trying to return result " + result); return(result); } //Log.Warning("Returning Null"); return(null); }
protected static Boolean Detonate_Prefix(ref CompExplosive __instance, Map map) { Log.Message("Detonate"); Patch.LogNULL(map, "map"); if (__instance.parent.SpawnedOrAnyParentSpawned) { //Cache Position before Killing parent. IntVec3 _Position = __instance.parent.PositionHeld; CompProperties_Explosive props = __instance.Props; float num = __instance.ExplosiveRadius(); if (props.explosiveExpandPerFuel > 0f && __instance.parent.GetComp <CompRefuelable>() != null) { __instance.parent.GetComp <CompRefuelable>().ConsumeFuel(__instance.parent.GetComp <CompRefuelable>().Fuel); } if (props.destroyThingOnExplosionSize <= num && !__instance.parent.Destroyed) { __instance.destroyedThroughDetonation = true; __instance.parent.Kill(null, null); } //__instance.EndWickSustainer(); //EndWickSustainer is Private so use Reflection to invoke the method. MethodInfo _EndWickSustainer = typeof(CompExplosive).GetMethod("EndWickSustainer", BindingFlags.NonPublic | BindingFlags.Instance); Patch.LogNULL(_EndWickSustainer, "_EndWickSustainer"); if (_EndWickSustainer != null) { _EndWickSustainer.Invoke(__instance, null); } __instance.wickStarted = false; if (map == null) { Log.Warning("Tried to detonate CompExplosive in a null map.", false); } else { if (props.explosionEffect != null) { Effecter effecter = props.explosionEffect.Spawn(); //effecter.Trigger(new TargetInfo(__instance.parent.PositionHeld, map, false), new TargetInfo(__instance.parent.PositionHeld, map, false)); effecter.Trigger(new TargetInfo(_Position, map, false), new TargetInfo(_Position, map, false)); effecter.Cleanup(); } IntVec3 positionHeld = __instance.parent.PositionHeld; float radius = num; DamageDef explosiveDamageType = props.explosiveDamageType; //Get the instigator unsing Reflection because it is private FieldInfo _Instigator = typeof(CompExplosive).GetField("instigator", BindingFlags.NonPublic | BindingFlags.Instance); Patch.LogNULL(_Instigator, "_Instigator"); Thing _InstigatorValue = (Thing)_Instigator.GetValue(__instance); Thing thing = _InstigatorValue ?? __instance.parent; int damageAmountBase = props.damageAmountBase; float armorPenetrationBase = props.armorPenetrationBase; SoundDef explosionSound = props.explosionSound; ThingDef postExplosionSpawnThingDef = props.postExplosionSpawnThingDef; float postExplosionSpawnChance = props.postExplosionSpawnChance; int postExplosionSpawnThingCount = props.postExplosionSpawnThingCount; // GenExplosion.DoExplosion(positionHeld, map, radius, explosiveDamageType, thing, damageAmountBase, armorPenetrationBase, explosionSound, null, null, null, postExplosionSpawnThingDef, postExplosionSpawnChance, postExplosionSpawnThingCount, props.applyDamageToExplosionCellsNeighbors, props.preExplosionSpawnThingDef, props.preExplosionSpawnChance, props.preExplosionSpawnThingCount, props.chanceToStartFire, props.damageFalloff); GenExplosion.DoExplosion(_Position, map, radius, explosiveDamageType, thing, damageAmountBase, armorPenetrationBase, explosionSound, null, null, null, postExplosionSpawnThingDef, postExplosionSpawnChance, postExplosionSpawnThingCount, props.applyDamageToExplosionCellsNeighbors, props.preExplosionSpawnThingDef, props.preExplosionSpawnChance, props.preExplosionSpawnThingCount, props.chanceToStartFire, props.damageFalloff); } } return(false); }
public override void PostSpawnSetup(bool respawningAfterLoad) { base.PostSpawnSetup(respawningAfterLoad); this.compexplosive = this.parent.GetComp <CompExplosive>(); this.comppower = this.parent.GetComp <CompPowerTrader>(); }
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) { Log.Message("Using VEF_AttackTargetFinder"); Thing searcherThing = searcher.Thing; Pawn searcherPawn = searcher as Pawn; Verb verb = searcher.CurrentEffectiveVerb; Log.Message("searcher is " + searcherPawn.Label); Log.Message("Attack Verb is " + verb.ToString()); 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) { Log.Message("Beginning of innerValidator - Validating for " + t.Thing.Label); Thing thing = t.Thing; if (t == searcher) { Log.Message("IAttackTarget is Searcher - Invalid target"); return(false); } if (minDistSquared > 0f && (float)(searcherThing.Position - thing.Position).LengthHorizontalSquared < minDistSquared) { Log.Message("Verb has minDistance and IAttackTarget is within minimum distance - Invalid target"); return(false); } if (!canTakeTargetsCloserThanEffectiveMinRange) { Log.Message("Searcher cannot attack targets closer that verb.verbProps.EffectiveMinRange"); float num2 = verb.verbProps.EffectiveMinRange(thing, searcherThing); if (num2 > 0f && (float)(searcherThing.Position - thing.Position).LengthHorizontalSquared < num2 * num2) { Log.Message("Distance between Searcher and IAttackTarget is greater than 0, but less than verb.verbProps.EffectiveMinimumRange - Invalid target"); return(false); } } if (maxTravelRadiusFromLocus < 9999f && (float)(thing.Position - locus).LengthHorizontalSquared > maxLocusDistSquared) { Log.Message("Seacrher has limited permissable movement and IAttackTarget is outside of that distance - Invalid target"); return(false); } if (!searcherThing.HostileTo(thing)) { Log.Message("Searcher is not hostile towards IAttackTarget - Invalid target"); return(false); } if (validator != null && !validator(thing)) { Log.Message("Searcher has validator and validator failed. Validator checked for " + validator.GetType().ToString()); return(false); } if (searcherPawn != null) { Log.Message("Searcher is Pawn - Get Lord"); Lord lord = searcherPawn.GetLord(); if (lord != null && !lord.LordJob.ValidateAttackTarget(searcherPawn, thing)) { Log.Message("Lord is in incorrect state - Return false"); return(false); } } if ((byte)(flags & TargetScanFlags.NeedLOSToAll) != 0 && !searcherThing.CanSee(thing, losValidator)) { Log.Message("Searher needs LOS to some or all targets, but cannot see target."); if (t is Pawn) { Log.Message("IAttackTarget is Pawn"); if ((byte)(flags & TargetScanFlags.NeedLOSToPawns) != 0) { Log.Message("Searcher needs LOS to Pawn - Invalid target"); return(false); } } else if ((byte)(flags & TargetScanFlags.NeedLOSToNonPawns) != 0) { Log.Message("IAttackTarget is nonPawn"); Log.Message("Searcher needs LOS to NonPawns - Invalid target"); return(false); } } if ((byte)(flags & TargetScanFlags.NeedThreat) != 0 && t.ThreatDisabled(searcher)) { Log.Message("Searcher needs Threat, IAttackTarget is not threat - Invalid target"); return(false); } Pawn pawn = t as Pawn; if (onlyTargetMachines && pawn != null && pawn.RaceProps.IsFlesh) { Log.Message("Verb is EMP and target is flesh - Invalid target"); return(false); } if ((byte)(flags & TargetScanFlags.NeedNonBurning) != 0 && thing.IsBurning()) { Log.Message("Verb is incendiary and target is already burning - Invalid target"); return(false); } if (searcherThing.def.race != null && searcherThing.def.race.intelligence >= Intelligence.Humanlike) { Log.Message("Searcher is ToolUser - Validating use of Explosives"); CompExplosive compExplosive = thing.TryGetComp <CompExplosive>(); if (compExplosive != null && compExplosive.wickStarted) { Log.Message("Explosive is already lit - Invalid verb"); return(false); } } if (thing.def.size.x == 1 && thing.def.size.z == 1) { if (thing.Position.Fogged(thing.Map)) { Log.Message("IAttackTarget is in Fog - Invalid target"); return(false); } } else { bool flag2 = false; CellRect.CellRectIterator iterator = thing.OccupiedRect().GetIterator(); while (!iterator.Done()) { if (!iterator.Current.Fogged(thing.Map)) { Log.Message("IAttackTarget is not in Fog - return true"); flag2 = true; break; } iterator.MoveNext(); } if (!flag2) { return(false); } } Log.Message("IAttackTarget is valid target"); return(true); }; if (HasRangedAttack(searcher)) { Log.Message(searcher.Thing.Label + " has ranged verb."); tmpTargets.Clear(); tmpTargets.AddRange(searcherThing.Map.attackTargetsCache.GetPotentialTargetsFor(searcher)); Log.Message("initializing tmpTargets"); if ((byte)(flags & TargetScanFlags.NeedReachable) != 0) { Log.Message("TargetScanFlags.NeedReachable"); Predicate <IAttackTarget> oldValidator = innerValidator; innerValidator = ((IAttackTarget t) => oldValidator(t) && CanReach(searcherThing, t.Thing, canBash)); } bool flag = false; if (tmpTargets.Count == 0) { Log.Message("There are no tmpTargets - return null"); return(null); } else { Log.Message("There are " + tmpTargets.Count + " tmpTargets"); } for (int i = 0; i < tmpTargets.Count; i++) { Log.Message("Iterating tmpTargets to check for targets that can be hit from current location. Iteration " + i); IAttackTarget attackTarget = tmpTargets[i]; if (attackTarget.Thing.Position.InHorDistOf(searcherThing.Position, maxDist) && innerValidator(attackTarget) && CanShootAtFromCurrentPosition(attackTarget, searcher, verb)) { Log.Message("tempTarget " + i + " can be hit from current position."); flag = true; break; } Log.Message("tempTarget " + i + " cannot be hit from current position."); } IAttackTarget result = null; if (flag) { Log.Message("A target can be shot from current position. Clearing tempTargets outside of range and picking one."); tmpTargets.RemoveAll((IAttackTarget x) => !x.Thing.Position.InHorDistOf(searcherThing.Position, maxDist) || !innerValidator(x)); result = GetRandomShootingTargetByScore(tmpTargets, searcher, verb); Log.Message("Target that can be shot from present location is: " + result.Thing.ToString()); } else { Log.Message("No target can be hit from current position. Refining validator..."); Predicate <Thing> validator2; if ((byte)(flags & TargetScanFlags.NeedReachableIfCantHitFromMyPos) != 0 && (byte)(flags & TargetScanFlags.NeedReachable) == 0) { Log.Message("Using validator2 where (byte)TargetScanFalgs flags are not 0"); validator2 = ((Thing t) => innerValidator((IAttackTarget)t) && (CanReach(searcherThing, t, canBash) || CanShootAtFromCurrentPosition((IAttackTarget)t, searcher, verb))); } else { Log.Message("Using validator2 where (byte)TargetScanFlags flags are 0"); validator2 = ((Thing t) => innerValidator((IAttackTarget)t)); } Log.Message("--- MARKER ---"); result = (IAttackTarget)GenClosest.ClosestThing_Global(searcherThing.Position, tmpTargets, maxDist, validator2, null); if (result == null) { Log.Message("Taregt selection complete. Clearing tmpTargets. There is no valid target"); } else { Log.Message("Taregt selection complete. Clearing tmpTargets. Final target is: " + result.Thing.ToString()); } } 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 = 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); }
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)) { return(false); } } if ((flags & TargetScanFlags.NeedLOSToAll) != 0) { if (losValidator != null && (!losValidator(searcherThing.Position) || !losValidator(thing.Position))) { return(false); } if (!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 || (flags & TargetScanFlags.NeedAutoTargetable) != 0) && t.ThreatDisabled(searcher)) { return(false); } if ((flags & TargetScanFlags.NeedAutoTargetable) != 0 && !IsAutoTargetable(t)) { return(false); } if ((flags & TargetScanFlags.NeedActiveThreat) != 0 && !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) != 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; foreach (IntVec3 item in thing.OccupiedRect()) { if (!item.Fogged(thing.Map)) { flag2 = true; break; } } if (!flag2) { return(false); } } return(true); }; if (HasRangedAttack(searcher) && (searcherPawn == null || !searcherPawn.InAggroMentalState)) { tmpTargets.Clear(); tmpTargets.AddRange(searcherThing.Map.attackTargetsCache.GetPotentialTargetsFor(searcher)); if ((flags & TargetScanFlags.NeedReachable) != 0) { Predicate <IAttackTarget> oldValidator2 = innerValidator; innerValidator = ((IAttackTarget t) => oldValidator2(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; if (flag) { tmpTargets.RemoveAll((IAttackTarget x) => !x.Thing.Position.InHorDistOf(searcherThing.Position, maxDist) || !innerValidator(x)); result = GetRandomShootingTargetByScore(tmpTargets, searcher, verb); } else { result = (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); } tmpTargets.Clear(); return(result); } if (searcherPawn != null && searcherPawn.mindState.duty != null && searcherPawn.mindState.duty.radius > 0f && !searcherPawn.InMentalState) { Predicate <IAttackTarget> oldValidator = innerValidator; innerValidator = delegate(IAttackTarget t) { if (!oldValidator(t)) { return(false); } return(t.Thing.Position.InHorDistOf(searcherPawn.mindState.duty.focus.Cell, searcherPawn.mindState.duty.radius) ? true : false); }; } 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); 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; } } } return(attackTarget2); }
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.", 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); } 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); }
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); }