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

            for (int i = 0; i < rawTargets.Count; i++)
            {
                PCF_AttackTargetFinder.tmpTargetScores.Add(float.MinValue);
                PCF_AttackTargetFinder.tmpCanShootAtTarget.Add(false);
                if (rawTargets[i] != searcher)
                {
                    bool flag = PCF_AttackTargetFinder.CanShootAtFromCurrentPosition(rawTargets[i], searcher, verb);
                    PCF_AttackTargetFinder.tmpCanShootAtTarget[i] = flag;
                    if (flag)
                    {
                        float shootingTargetScore = PCF_AttackTargetFinder.GetShootingTargetScore(rawTargets[i], searcher, verb);
                        PCF_AttackTargetFinder.tmpTargetScores[i] = shootingTargetScore;
                        if (attackTarget == null || shootingTargetScore > num)
                        {
                            attackTarget = rawTargets[i];
                            num          = shootingTargetScore;
                        }
                    }
                }
            }
            if (num < 1f)
            {
                if (attackTarget != null)
                {
                    PCF_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 (PCF_AttackTargetFinder.tmpCanShootAtTarget[j])
                        {
                            float num3 = PCF_AttackTargetFinder.tmpTargetScores[j];
                            if (num3 >= num2)
                            {
                                float second = Mathf.InverseLerp(num - 30f, num, num3);
                                PCF_AttackTargetFinder.availableShootingTargets.Add(new Pair <IAttackTarget, float>(rawTargets[j], second));
                            }
                        }
                    }
                }
            }
            return(PCF_AttackTargetFinder.availableShootingTargets);
        }
コード例 #2
0
        public static void CheckForAutoAttack(JobDriver jobDriver)
        {
            List <Hediff> hediffs = jobDriver.pawn.health.hediffSet.hediffs;
            int           hediff  = hediffs.Count;

            for (int i = 0; i < hediff; i++)
            {
                HediffComp_VerbGiverExtended verbGiverExtended = hediffs[i].TryGetComp <HediffComp_VerbGiverExtended>();
                if (verbGiverExtended != null)
                {
                    List <Verb> allVerbs = verbGiverExtended.AllVerbs;
                    int         radVerb  = Random.Range(0, allVerbs.Count);
                    if (allVerbs[radVerb] != null && verbGiverExtended.canAutoAttack && verbGiverExtended.canAttack)
                    {
                        TargetScanFlags targetScanFlags = TargetScanFlags.NeedLOSToPawns | TargetScanFlags.NeedLOSToNonPawns | TargetScanFlags.NeedThreat;
                        if (allVerbs[radVerb].IsIncendiary())
                        {
                            targetScanFlags |= TargetScanFlags.NeedNonBurning;
                        }
                        Thing thing = (Thing)PCF_AttackTargetFinder.BestShootTargetFromCurrentPosition(jobDriver.pawn, allVerbs[radVerb], targetScanFlags, null, 0f, 9999f);
                        if (thing != null && !allVerbs[radVerb].IsMeleeAttack)
                        {
                            verbGiverExtended.rangedVerbWarmupTime = allVerbs[radVerb].verbProps.warmupTime;
                            allVerbs[radVerb].verbProps.warmupTime = 0f;
                            allVerbs[radVerb].TryStartCastOn(thing, false, true);
                            allVerbs[radVerb].verbProps.warmupTime = verbGiverExtended.rangedVerbWarmupTime;
                        }
                    }
                    verbGiverExtended.canAttack = false;
                }
            }
        }
コード例 #3
0
        public static void CheckForAutoAttack(JobDriver jobDriver)
        {
            List <Hediff> hediffs = jobDriver.pawn.health.hediffSet.hediffs;

            foreach (Hediff hediff in hediffs)
            {
                HediffComp_VerbGiverExtended verbGiverExtended = hediff.TryGetComp <HediffComp_VerbGiverExtended>();
                if (verbGiverExtended != null) // for each comp that gives verbs do this:
                {
                    List <Verb> allVerbs = new List <Verb>(verbGiverExtended.AllVerbs.SkipWhile((Verb verb) => verb is Verb_CastPsycast));
                    int         radVerb  = Random.Range(0, allVerbs.Count);
                    if (allVerbs[radVerb] != null && verbGiverExtended.canAutoAttack && verbGiverExtended.canAttack) // take a random verb that can attack
                    {
                        TargetScanFlags targetScanFlags = TargetScanFlags.NeedLOSToPawns | TargetScanFlags.NeedLOSToNonPawns | TargetScanFlags.NeedThreat;
                        if (allVerbs[radVerb].IsIncendiary())
                        {
                            targetScanFlags |= TargetScanFlags.NeedNonBurning;
                        }
                        // find best thing to attack
                        Thing thing = (Thing)PCF_AttackTargetFinder.BestShootTargetFromCurrentPosition(jobDriver.pawn, allVerbs[radVerb], targetScanFlags, null, 0f, 9999f);
                        if (thing != null && !allVerbs[radVerb].IsMeleeAttack) // attack (weird shit inbetween)
                        {
                            verbGiverExtended.rangedVerbWarmupTime = allVerbs[radVerb].verbProps.warmupTime;
                            allVerbs[radVerb].verbProps.warmupTime = 0f;
                            allVerbs[radVerb].TryStartCastOn(thing, false, true);
                            allVerbs[radVerb].verbProps.warmupTime = verbGiverExtended.rangedVerbWarmupTime;
                        }
                    }
                    verbGiverExtended.canAttack = false;
                }
            }
        }
 private static IAttackTarget GetRandomShootingTargetByScore(List <IAttackTarget> targets, IAttackTargetSearcher searcher, Verb verb)
 {
     if (PCF_AttackTargetFinder.GetAvailableShootingTargetsByScore(targets, searcher, verb).TryRandomElementByWeight((Pair <IAttackTarget, float> x) => x.Second, out Pair <IAttackTarget, float> pair))
     {
         return(pair.First);
     }
     return(null);
 }
 public static IAttackTarget BestShootTargetFromCurrentPosition(IAttackTargetSearcher searcher, Verb verb, TargetScanFlags flags, Predicate <Thing> validator = null, float minDistance = 0f, float maxDistance = 9999f)
 {
     if (verb == null)
     {
         Log.Error("BestShootTargetFromCurrentPosition with " + searcher.ToStringSafe <IAttackTargetSearcher>() + " who has no attack verb.", false);
         return(null);
     }
     return(PCF_AttackTargetFinder.BestAttackTarget(searcher, verb, flags, validator, Mathf.Max(minDistance, verb.verbProps.minRange), Mathf.Min(maxDistance, verb.verbProps.range), default(IntVec3), float.MaxValue, false, false));
 }
        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;
            if (target is Pawn pawn && pawn.RaceProps.Animal && pawn.Faction != null && !pawn.IsFighting())
            {
                num -= 50f;
            }
            num += PCF_AttackTargetFinder.FriendlyFireBlastRadiusTargetScoreOffset(target, searcher, verb);
            return(num + PCF_AttackTargetFinder.FriendlyFireConeTargetScoreOffset(target, searcher, verb));
        }
        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);
        }