Esempio n. 1
0
        /// <summary>
        ///     Figures out the best location to use this Ability at. Default implementation returns the enemy target, closest ally
        ///     or the caster.
        /// </summary>
        /// <param name="abilityDef">Ability Def for the AI.</param>
        /// <param name="pawn">Pawn to take in account.</param>
        /// <returns>Targeting location or Pawn.</returns>
        public virtual LocalTargetInfo TargetAbilityFor(AbilityAIDef abilityDef, Pawn pawn)
        {
            if (abilityDef.usedOnCaster)
            {
                return(pawn);
            }
            if (abilityDef.canTargetAlly)
            {
                return(GenClosest.ClosestThingReachable(pawn.Position, pawn.Map,
                                                        ThingRequest.ForGroup(ThingRequestGroup.Pawn), PathEndMode.OnCell,
                                                        TraverseParms.For(TraverseMode.NoPassClosedDoors), abilityDef.maxRange,
                                                        thing => AbilityUtility.AreAllies(pawn, thing)));
            }
            if (pawn.mindState.enemyTarget != null && pawn.mindState.enemyTarget is Pawn targetPawn)
            {
                if (!targetPawn.Dead)
                {
                    return(pawn.mindState.enemyTarget);
                }
            }
            else
            {
                if (pawn.mindState.enemyTarget != null && !(pawn.mindState.enemyTarget is Corpse))
                {
                    return(pawn.mindState.enemyTarget);
                }
            }

            return(null);
        }
Esempio n. 2
0
        /// <summary>
        ///     Grab all viable target candidates.
        /// </summary>
        /// <param name="abilityDef">Ability Def to take in account.</param>
        /// <param name="pawn">Caster Pawn.</param>
        /// <param name="customPredicate">If set it overrides the default predicate.</param>
        /// <param name="pawnsToTest">How many pawns to test at max before stopping. Default is 30.</param>
        /// <returns>Things that are viable.</returns>
        public virtual IEnumerable <Thing> GrabTargets(AbilityAIDef abilityDef, Pawn pawn,
                                                       Predicate <Thing> customPredicate = null, int pawnsToTest = 30)
        {
            //Make a list of candidates.
            var potentionalTargets          = new List <Thing>();
            Predicate <Thing> pawnPredicate = null;

            if (customPredicate != null)
            {
                pawnPredicate = customPredicate;
            }
            else if (abilityDef.canTargetAlly)
            {
                pawnPredicate = delegate(Thing thing)
                {
                    //Count own faction and faction whose goodwill they got above 50% as allies.
                    if (AbilityUtility.AreAllies(pawn, thing))
                    {
                        return(true);
                    }
                    return(false);
                }
            }
            ;
            else
            {
                pawnPredicate = delegate(Thing thing)
                {
                    var thingPawn = thing as Pawn;

                    //Count anything hostile as a target.
                    if (thingPawn != null)
                    {
                        if (!thingPawn.Downed && thing.HostileTo(pawn))
                        {
                            return(true);
                        }
                        else if (thing.HostileTo(pawn))
                        {
                            return(true);
                        }
                    }

                    return(false);
                }
            };

            //Max 'pawnsToTest' shall we grab.
            for (var i = 0; i < pawnsToTest; i++)
            {
                var grabResult = GenClosest.ClosestThingReachable(pawn.Position, pawn.Map,
                                                                  ThingRequest.ForGroup(ThingRequestGroup.Pawn), PathEndMode.OnCell,
                                                                  TraverseParms.For(TraverseMode.NoPassClosedDoors),
                                                                  abilityDef.maxRange,
                                                                  thing => pawn != thing && !potentionalTargets.Contains(thing) &&
                                                                  (thing.Position - pawn.Position).LengthHorizontal >= abilityDef.minRange &&
                                                                  pawnPredicate(thing));

                //If found nothing, then break.
                if (grabResult == null)
                {
                    break;
                }

                potentionalTargets.Add(grabResult);

                yield return(grabResult);
            }
        }
    }
Esempio n. 3
0
        /// <summary>
        ///     Picks the best candidate Pawn out of up to 10 other.
        /// </summary>
        /// <param name="abilityDef">Ability Def to optionally take in account.</param>
        /// <param name="pawn">Pawn using the Ability.</param>
        /// <returns>Candidate Pawn if found, null if not.</returns>
        public virtual Pawn PickBestClosestPawn(AbilityAIDef abilityDef, Pawn pawn)
        {
            Pawn bestPawn   = null;
            var  bestHealth = 1f;

            var checkedThings = new List <Thing>();

            //Check 10 closest for optimal target.
            for (var i = 0; i < 10; i++)
            {
                var foundThing = GenClosest.ClosestThingReachable(pawn.Position, pawn.Map,
                                                                  ThingRequest.ForGroup(ThingRequestGroup.Pawn), PathEndMode.OnCell,
                                                                  TraverseParms.For(TraverseMode.NoPassClosedDoors), abilityDef.maxRange,
                                                                  thing => pawn != thing && !checkedThings.Contains(thing) && AbilityUtility.AreAllies(pawn, thing));

                //Found no valid candidate.
                if (foundThing == null)
                {
                    break;
                }

                checkedThings.Add(foundThing);

                var foundPawn = foundThing as Pawn;

                if (foundPawn != null)
                {
                    if (foundPawn.health.summaryHealth.SummaryHealthPercent < bestHealth)
                    {
                        bestPawn   = foundPawn;
                        bestHealth = foundPawn.health.summaryHealth.SummaryHealthPercent;
                    }
                }
            }

            return(bestPawn);
        }