private static List <Pair <IAttackTarget, float> > GetAvailableShootingTargetsByScore(List <IAttackTarget> rawTargets, IAttackTargetSearcher searcher, Verb verb)
        {
            ARA_AttackTargetFinder.availableShootingTargets.Clear();
            if (rawTargets.Count == 0)
            {
                return(ARA_AttackTargetFinder.availableShootingTargets);
            }
            ARA_AttackTargetFinder.tmpTargetScores.Clear();
            ARA_AttackTargetFinder.tmpCanShootAtTarget.Clear();
            float         num          = 0f;
            IAttackTarget attackTarget = null;

            for (int i = 0; i < rawTargets.Count; i++)
            {
                ARA_AttackTargetFinder.tmpTargetScores.Add(-3.40282347E+38f);
                ARA_AttackTargetFinder.tmpCanShootAtTarget.Add(false);
                if (rawTargets[i] != searcher)
                {
                    bool flag = ARA_AttackTargetFinder.CanShootAtFromCurrentPosition(rawTargets[i], searcher, verb);
                    ARA_AttackTargetFinder.tmpCanShootAtTarget[i] = flag;
                    if (flag)
                    {
                        float shootingTargetScore = ARA_AttackTargetFinder.GetShootingTargetScore(rawTargets[i], searcher, verb);
                        ARA_AttackTargetFinder.tmpTargetScores[i] = shootingTargetScore;
                        if (attackTarget == null || shootingTargetScore > num)
                        {
                            attackTarget = rawTargets[i];
                            num          = shootingTargetScore;
                        }
                    }
                }
            }
            if (num < 1f)
            {
                if (attackTarget != null)
                {
                    ARA_AttackTargetFinder.availableShootingTargets.Add(new Pair <IAttackTarget, float>(attackTarget, 1f));
                }
            }
            else
            {
                float num2 = num - 30f;
                for (int j = 0; j < rawTargets.Count; j++)
                {
                    if (rawTargets[j] != searcher)
                    {
                        if (ARA_AttackTargetFinder.tmpCanShootAtTarget[j])
                        {
                            float num3 = ARA_AttackTargetFinder.tmpTargetScores[j];
                            if (num3 >= num2)
                            {
                                float second = Mathf.InverseLerp(num - 30f, num, num3);
                                ARA_AttackTargetFinder.availableShootingTargets.Add(new Pair <IAttackTarget, float>(rawTargets[j], second));
                            }
                        }
                    }
                }
            }
            return(ARA_AttackTargetFinder.availableShootingTargets);
        }
        private static IAttackTarget GetRandomShootingTargetByScore(List <IAttackTarget> targets, IAttackTargetSearcher searcher, Verb verb)
        {
            Pair <IAttackTarget, float> pair;

            if (ARA_AttackTargetFinder.GetAvailableShootingTargetsByScore(targets, searcher, verb).TryRandomElementByWeight((Pair <IAttackTarget, float> x) => x.Second, out pair))
            {
                return(pair.First);
            }
            return(null);
        }
        private static float GetShootingTargetScore(IAttackTarget target, IAttackTargetSearcher searcher, Verb verb)
        {
            float num = 60f;

            num -= Mathf.Min((target.Thing.Position - searcher.Thing.Position).LengthHorizontal, 40f);
            if (target.TargetCurrentlyAimingAt == searcher.Thing)
            {
                num += 10f;
            }
            if (searcher.LastAttackedTarget == target.Thing && Find.TickManager.TicksGame - searcher.LastAttackTargetTick <= 300)
            {
                num += 40f;
            }
            num -= CoverUtility.CalculateOverallBlockChance(target.Thing.Position, searcher.Thing.Position, searcher.Thing.Map) * 10f;
            Pawn pawn = target as Pawn;

            if (pawn != null && pawn.RaceProps.Animal && pawn.Faction != null && !pawn.IsFighting())
            {
                num -= 50f;
            }
            return(num + ARA_AttackTargetFinder.FriendlyFireShootingTargetScoreOffset(target, searcher, verb));
        }
 public static IAttackTarget BestShootTargetFromCurrentPosition(IAttackTargetSearcher searcher, Predicate <Thing> validator, float maxDistance, float minDistance, TargetScanFlags flags)
 {
     return(ARA_AttackTargetFinder.BestAttackTarget(searcher, flags, validator, minDistance, maxDistance, default(IntVec3), 3.40282347E+38f, false));
 }
        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);
        }
Example #6
0
        static bool Prefix(ref JobGiver_Manhunter __instance, ref Job __result, ref Pawn pawn)
        {
            //Log.Warning("Man hunter detected");
            if (!pawn.RaceProps.Animal)
            {
                return(true);
            }

            bool hasRangedVerb = false;

            List <Verb> verbList  = pawn.verbTracker.AllVerbs;
            List <Verb> rangeList = new List <Verb>();

            for (int i = 0; i < verbList.Count; i++)
            {
                //Log.Warning("Checkity");
                //It corresponds with verbs anyway
                if (!verbList[i].verbProps.IsMeleeAttack)
                {
                    rangeList.Add(verbList[i]);
                    hasRangedVerb = true;
                    //Log.Warning("Added Ranged Verb");
                }
            }

            if (hasRangedVerb == false)
            {
                // Log.Warning("I don't have range verb");
                return(true);
            }
            // this.SetCurMeleeVerb(updatedAvailableVerbsList.RandomElementByWeight((VerbEntry ve) => ve.SelectionWeight).verb);
            Verb rangeVerb = rangeList.RandomElementByWeight((Verb rangeItem) => rangeItem.verbProps.commonality);

            if (rangeVerb == null)
            {
                //Log.Warning("Can't get random range verb");
                return(true);
            }

            //Seek enemy in conventional way.
            Thing enemyTarget = (Thing)ARA_AttackTargetFinder.BestAttackTarget((IAttackTargetSearcher)pawn, TargetScanFlags.NeedThreat | TargetScanFlags.NeedReachable, (Predicate <Thing>)(x =>
                                                                                                                                                                                            x is Pawn || x is Building), 0.0f, 9999, new IntVec3(), float.MaxValue, false);

            //Seek thing hiding in embrasure.
            if (enemyTarget == null)
            {
                enemyTarget = (Thing)ARA_AttackTargetFinder.BestAttackTarget((IAttackTargetSearcher)pawn, TargetScanFlags.NeedThreat, (Predicate <Thing>)(x =>
                                                                                                                                                          x is Pawn || x is Building), 0.0f, 9999, new IntVec3(), float.MaxValue, false);
            }

            if (enemyTarget == null)
            {
                //Log.Warning("I can't find anything to fight.");
                return(true);
            }

            //Check if enemy directly next to pawn
            if (enemyTarget.Position.DistanceTo(pawn.Position) < rangeVerb.verbProps.minRange)
            {
                //If adjacent melee attack
                if (enemyTarget.Position.AdjacentTo8Way(pawn.Position))
                {
                    __result = new Job(JobDefOf.AttackMelee, enemyTarget)
                    {
                        maxNumMeleeAttacks     = 1,
                        expiryInterval         = Rand.Range(420, 900),
                        attackDoorIfTargetLost = false
                    };
                    return(false);
                }
                return(true);
            }

            //Log.Warning("got list of ranged verb");
            //Log.Warning("Attempting flag");
            bool flag1 = (double)CoverUtility.CalculateOverallBlockChance(pawn.Position, enemyTarget.Position, pawn.Map) > 0.00999999977648258;
            bool flag2 = pawn.Position.Standable(pawn.Map);
            bool flag3 = rangeVerb.CanHitTarget(enemyTarget);
            bool flag4 = (pawn.Position - enemyTarget.Position).LengthHorizontalSquared < 25;

            if (flag1 && flag2 && flag3 || flag4 && flag3)
            {
                //Log.Warning("Shooting");
                __result = new Job(DefDatabase <JobDef> .GetNamed("PI_AnimalRangeAttack"), enemyTarget, JobGiver_AIFightEnemy.ExpiryInterval_ShooterSucceeded.RandomInRange, true)
                {
                    verbToUse = rangeVerb
                };
                return(false);
            }
            IntVec3 dest;
            bool    canShootCondition = false;

            canShootCondition = CastPositionFinder.TryFindCastPosition(new CastPositionRequest
            {
                caster              = pawn,
                target              = enemyTarget,
                verb                = rangeVerb,
                maxRangeFromTarget  = rangeVerb.verbProps.range,
                wantCoverFromTarget = false,
                maxRegions          = 50
            }, out dest);

            if (!canShootCondition)
            {
                //Log.Warning("I can't move to shooting position");

                return(true);
            }

            if (dest == pawn.Position)
            {
                //Log.Warning("I will stay here and attack");
                __result = new Job(DefDatabase <JobDef> .GetNamed("PI_AnimalRangeAttack"), enemyTarget, JobGiver_AIFightEnemy.ExpiryInterval_ShooterSucceeded.RandomInRange, true)
                {
                    verbToUse = rangeVerb
                };
                return(false);
            }
            //Log.Warning("Going to new place");
            __result = new Job(JobDefOf.Goto, (LocalTargetInfo)dest)
            {
                expiryInterval        = JobGiver_AIFightEnemy.ExpiryInterval_ShooterSucceeded.RandomInRange,
                checkOverrideOnExpire = true
            };
            return(false);
        }