static void Postfix(CompExplosive __instance)
 {
     if (__instance is CompExplosiveCustom custom)
     {
         custom.OnPostDetonated();
     }
 }
Exemplo n.º 2
0
        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;
        }
Exemplo n.º 4
0
        // ===================== 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;
        }
Exemplo n.º 5
0
        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"));
            }
        }
Exemplo n.º 6
0
        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();
            }
        }
Exemplo n.º 7
0
 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;
 }
Exemplo n.º 8
0
        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;
            }
        }
Exemplo n.º 9
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);
            }
Exemplo n.º 11
0
        // 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;
                    }
                }
            }
        }
Exemplo n.º 12
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);
        }
Exemplo n.º 13
0
        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);
        }
Exemplo n.º 14
0
 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);
        }
Exemplo n.º 16
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 = 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);
        }
Exemplo n.º 18
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 ((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);
        }