private void DeregisterTarget(IAttackTarget target) { if (!allTargets.Contains(target)) { Log.Warning("Tried to deregister " + target + " but it's not in " + GetType()); } else { allTargets.Remove(target); foreach (KeyValuePair <Faction, HashSet <IAttackTarget> > item in targetsHostileToFaction) { HashSet <IAttackTarget> value = item.Value; value.Remove(target); } Pawn pawn = target as Pawn; if (pawn != null) { pawnsInAggroMentalState.Remove(pawn); } } }
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)); }
private int GetMaxPreferredReservationsCount(IAttackTarget target) { int num = 0; Thing thing = target.Thing; CellRect cellRect = thing.OccupiedRect(); foreach (IntVec3 c in cellRect.ExpandedBy(1)) { if (!cellRect.Contains(c)) { if (c.InBounds(this.map)) { if (c.Standable(this.map)) { num++; } } } } return(num); }
public AttackTask(IActor actor, IActorTaskContext context, IAttackTarget target, ICombatAct tacticalAct, ITacticalActUsageService actService) : base(actor, context) { _actService = actService; TargetObject = target ?? throw new ArgumentNullException(nameof(target)); TacticalAct = tacticalAct ?? throw new ArgumentNullException(nameof(tacticalAct)); TargetNode = target.Node; var combatActDuration = tacticalAct.Stats.Duration.GetValueOrDefault(1); var durationBonus = GetDurationBonus(actor); var durationWithBonus = (int)Math.Round(GlobeMetrics.OneIterationLength * combatActDuration * durationBonus); Cost = durationWithBonus; }
private void RegisterTarget(IAttackTarget target) { if (allTargets.Contains(target)) { Log.Warning("Tried to register the same target twice " + target.ToStringSafe() + " in " + GetType()); } else { Thing thing = target.Thing; if (!thing.Spawned) { Log.Warning("Tried to register unspawned thing " + thing.ToStringSafe() + " in " + GetType()); } else if (thing.Map != map) { Log.Warning("Tried to register attack target " + thing.ToStringSafe() + " but its Map is not this one."); } else { allTargets.Add(target); List <Faction> allFactionsListForReading = Find.FactionManager.AllFactionsListForReading; for (int i = 0; i < allFactionsListForReading.Count; i++) { if (thing.HostileTo(allFactionsListForReading[i])) { if (!targetsHostileToFaction.ContainsKey(allFactionsListForReading[i])) { targetsHostileToFaction.Add(allFactionsListForReading[i], new HashSet <IAttackTarget>()); } targetsHostileToFaction[allFactionsListForReading[i]].Add(target); } } Pawn pawn = target as Pawn; if (pawn != null && pawn.InAggroMentalState) { pawnsInAggroMentalState.Add(pawn); } } } }
private static float FriendlyFireBlastRadiusTargetScoreOffset(IAttackTarget target, IAttackTargetSearcher searcher, Verb verb) { if (verb.verbProps.ai_AvoidFriendlyFireRadius <= 0f) { return(0f); } Map map = target.Thing.Map; IntVec3 position = target.Thing.Position; int num = GenRadial.NumCellsInRadius(verb.verbProps.ai_AvoidFriendlyFireRadius); float num2 = 0f; for (int i = 0; i < num; i++) { IntVec3 intVec = position + GenRadial.RadialPattern[i]; if (!intVec.InBounds(map)) { continue; } bool flag = true; List <Thing> thingList = intVec.GetThingList(map); for (int j = 0; j < thingList.Count; j++) { if (!(thingList[j] is IAttackTarget) || thingList[j] == target) { continue; } if (flag) { if (!GenSight.LineOfSight(position, intVec, map, skipFirstCell: true)) { break; } flag = false; } float num3 = (thingList[j] == searcher) ? 40f : ((!(thingList[j] is Pawn)) ? 10f : (thingList[j].def.race.Animal ? 7f : 18f)); num2 = ((!searcher.Thing.HostileTo(thingList[j])) ? (num2 - num3) : (num2 + num3 * 0.6f)); } } return(num2); }
public static bool IsActiveThreatTo(IAttackTarget target, Faction faction) { if (!target.Thing.HostileTo(faction)) { return(false); } if (!(target.Thing is IAttackTargetSearcher)) { return(false); } if (target.ThreatDisabled(null)) { return(false); } Pawn pawn = target.Thing as Pawn; if (pawn != null) { Lord lord = pawn.GetLord(); if (lord != null && lord.LordJob is LordJob_DefendAndExpandHive && (pawn.mindState.duty == null || pawn.mindState.duty.def != DutyDefOf.AssaultColony)) { return(false); } } Pawn pawn2 = target.Thing as Pawn; if (pawn2 != null && (pawn2.MentalStateDef == MentalStateDefOf.PanicFlee || pawn2.IsPrisoner)) { return(false); } if (target.Thing.Spawned) { TraverseParms traverseParms = (pawn2 == null) ? TraverseParms.For(TraverseMode.PassDoors, Danger.Deadly, false) : TraverseParms.For(pawn2, Danger.Deadly, TraverseMode.ByPawn, false); if (!target.Thing.Map.reachability.CanReachUnfogged(target.Thing.Position, traverseParms)) { return(false); } } return(true); }
protected override Job TryGiveJob(Pawn pawn) { IntVec3 intVec = (IntVec3)pawn.mindState.duty.focus; if (intVec.IsValid && (float)intVec.DistanceToSquared(pawn.Position) < 100.0 && intVec.GetRoom(pawn.Map, RegionType.Set_Passable) == pawn.GetRoom(RegionType.Set_Passable) && intVec.WithinRegions(pawn.Position, pawn.Map, 9, TraverseMode.NoPassClosedDoors, RegionType.Set_Passable)) { pawn.GetLord().Notify_ReachedDutyLocation(pawn); return(null); } if (!intVec.IsValid) { IAttackTarget attackTarget = default(IAttackTarget); if (!(from x in pawn.Map.attackTargetsCache.GetPotentialTargetsFor(pawn) where !x.ThreatDisabled() && x.Thing.Faction == Faction.OfPlayer && pawn.CanReach(x.Thing, PathEndMode.OnCell, Danger.Deadly, false, TraverseMode.PassAllDestroyableThings) select x).TryRandomElement <IAttackTarget>(out attackTarget)) { return(null); } intVec = attackTarget.Thing.Position; } if (!pawn.CanReach(intVec, PathEndMode.OnCell, Danger.Deadly, false, TraverseMode.PassAllDestroyableThings)) { return(null); } using (PawnPath path = pawn.Map.pathFinder.FindPath(pawn.Position, intVec, TraverseParms.For(pawn, Danger.Deadly, TraverseMode.PassAllDestroyableThings, false), PathEndMode.OnCell)) { IntVec3 cellBeforeBlocker = default(IntVec3); Thing thing = path.FirstBlockingBuilding(out cellBeforeBlocker, pawn); if (thing != null) { Job job = DigUtility.PassBlockerJob(pawn, thing, cellBeforeBlocker, this.canMineMineables, this.canMineNonMineables); if (job != null) { return(job); } } } return(new Job(JobDefOf.Goto, intVec, 500, true)); }
public static bool ShouldFleeFrom(Thing t, Pawn pawn, bool checkDistance, bool checkLOS) { if (t == pawn || (checkDistance && !t.Position.InHorDistOf(pawn.Position, 8f))) { return(false); } if (t.def.alwaysFlee) { return(true); } if (!t.HostileTo(pawn)) { return(false); } IAttackTarget attackTarget = t as IAttackTarget; if (attackTarget == null || attackTarget.ThreatDisabled(pawn) || !(t is IAttackTargetSearcher) || (checkLOS && !GenSight.LineOfSight(pawn.Position, t.Position, pawn.Map))) { return(false); } return(true); }
private static void RemoveAllReservationsAndDesignationsOnThis(Thing __instance) { if (__instance.def.category == ThingCategory.Mote) { return; } List <Map> maps = Find.Maps; for (int i = 0; i < maps.Count; i++) { maps[i].reservationManager.ReleaseAllForTarget(__instance); maps[i].physicalInteractionReservationManager.ReleaseAllForTarget(__instance); IAttackTarget attackTarget = __instance as IAttackTarget; if (attackTarget != null) { maps[i].attackTargetReservationManager.ReleaseAllForTarget(attackTarget); } maps[i].designationManager.RemoveAllDesignationsOn(__instance); } }
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 == (LocalTargetInfo)searcher.Thing) { num = (float)(num + 10.0); } if (searcher.LastAttackedTarget == (LocalTargetInfo)target.Thing && Find.TickManager.TicksGame - searcher.LastAttackTargetTick <= 300) { num = (float)(num + 40.0); } num = (float)(num - CoverUtility.CalculateOverallBlockChance(target.Thing.Position, searcher.Thing.Position, searcher.Thing.Map) * 10.0); Pawn pawn = target as Pawn; if (pawn != null && pawn.RaceProps.Animal && pawn.Faction != null && !pawn.IsFighting()) { num = (float)(num - 50.0); } return(num + AttackTargetFinder.FriendlyFireShootingTargetScoreOffset(target, searcher, verb)); }
private AttackParams CheckAttackAvailability(IActor actor, IAttackTarget target) { if (actor.Person.GetModuleSafe <ICombatActModule>() is null) { throw new NotSupportedException(); } var inventory = actor.Person.GetModuleSafe <IInventoryModule>(); var act = SelectActHelper.SelectBestAct(actor.Person.GetModule <ICombatActModule>().CalcCombatActs(), inventory); var isInDistance = act.CheckDistance(actor.Node, target.Node, _map); var targetIsOnLine = _map.TargetIsOnLine(actor.Node, target.Node); var attackParams = new AttackParams { IsAvailable = isInDistance && targetIsOnLine, TacticalAct = act }; return(attackParams); }
static bool CanShootAtShieldFromCurrentPosition(bool __result, IAttackTarget target, IAttackTargetSearcher searcher, Verb verb) { if (!Mod.Settings.EnableAIAttackTargetFinder) { return(__result); } if (__result == false) { try { var result = new FieldQuery(searcher.Thing.Map) .IsActive() .HostileTo(searcher.Thing.Faction) .Intersects( PositionUtility.ToVector3(searcher.Thing.Position), PositionUtility.ToVector3(target.Thing.Position)) .GetWithIntersects() .First(); if (result.Second == null) { return(false); } var distance = Vector3.Distance(searcher.Thing.TrueCenter(), result.Second.Value); var range = verb.verbProps.range; var isTarget = result.First.Emitters .Select(emitter => emitter.Thing) .Any(thing => thing == target.Thing); if (distance <= range && isTarget) { return(true); } } catch (InvalidOperationException) { } } return(__result); }
private static float FriendlyFireShootingTargetScoreOffset(IAttackTarget target, IAttackTargetSearcher searcher, Verb verb) { if (verb.verbProps.ai_AvoidFriendlyFireRadius <= 0.0) { return(0f); } Map map = target.Thing.Map; IntVec3 position = target.Thing.Position; int num = GenRadial.NumCellsInRadius(verb.verbProps.ai_AvoidFriendlyFireRadius); float num2 = 0f; for (int i = 0; i < num; i++) { IntVec3 intVec = position + GenRadial.RadialPattern[i]; if (intVec.InBounds(map)) { bool flag = true; List <Thing> thingList = intVec.GetThingList(map); for (int j = 0; j < thingList.Count; j++) { if (thingList[j] is IAttackTarget && thingList[j] != target) { if (flag) { if (!GenSight.LineOfSight(position, intVec, map, true, null, 0, 0)) { break; } flag = false; } float num3 = (float)((thingList[j] != searcher) ? ((!(thingList[j] is Pawn)) ? 10.0 : ((!thingList[j].def.race.Animal) ? 18.0 : 7.0)) : 40.0); num2 = (float)((!searcher.Thing.HostileTo(thingList[j])) ? (num2 - num3) : (num2 + num3 * 0.60000002384185791)); } } } } return(Mathf.Min(num2, 0f)); }
private static Thing FindTargetFor(Pawn pawn) { List <IAttackTarget> potentialTargetsFor = pawn.Map.attackTargetsCache.GetPotentialTargetsFor(pawn); int min = int.MaxValue; Thing targetFound = null; for (int i = 0; i < potentialTargetsFor.Count; i++) { IAttackTarget attackTarget = potentialTargetsFor[i]; if (!attackTarget.ThreatDisabled(pawn)) { Thing target = (Thing)attackTarget; int distance = target.Position.DistanceToSquared(pawn.Position); if (distance < min && pawn.CanReach(target, PathEndMode.OnCell, Danger.Deadly, false, TraverseMode.ByPawn)) { min = distance; targetFound = target; } } } return(targetFound); }
public static bool AnyHostileActiveThreatTo(Map map, Faction faction, out IAttackTarget threat, bool countDormantPawnsAsHostile = false) { foreach (IAttackTarget item in map.attackTargetsCache.TargetsHostileToFaction(faction)) { if (IsActiveThreatTo(item, faction)) { threat = item; return(true); } Pawn pawn; if (countDormantPawnsAsHostile && item.Thing.HostileTo(faction) && !item.Thing.Fogged() && !item.ThreatDisabled(null) && (pawn = item.Thing as Pawn) != null) { CompCanBeDormant comp = pawn.GetComp <CompCanBeDormant>(); if (comp != null && !comp.Awake) { threat = item; return(true); } } } threat = null; return(false); }
public static bool ShouldFleeFrom(Thing t, Pawn pawn, bool checkDistance, bool checkLOS) { bool result; if (t == pawn || (checkDistance && !t.Position.InHorDistOf(pawn.Position, 8f))) { result = false; } else if (t.def.alwaysFlee) { result = true; } else if (!t.HostileTo(pawn)) { result = false; } else { IAttackTarget attackTarget = t as IAttackTarget; result = (attackTarget != null && !attackTarget.ThreatDisabled(pawn) && t is IAttackTargetSearcher && (!checkLOS || GenSight.LineOfSight(pawn.Position, t.Position, pawn.Map, false, null, 0, 0))); } return(result); }
/// <summary> /// Get target score /// </summary> /// <param name="target"></param> /// <param name="searcher"></param> private static float GetShootingTargetScore(IAttackTarget target, IAttackTargetSearcher searcher) { 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; } //num += _ - add additional cost based on how close to friendly fire return(num * target.TargetPriorityFactor); }
private static float GetShootingTargetScore( IAttackTarget target, IAttackTargetSearcher searcher, Verb verb) { float num1 = 60f - Mathf.Min((target.Thing.Position - searcher.Thing.Position).LengthHorizontal, 40f); if (target.TargetCurrentlyAimingAt == (LocalTargetInfo)searcher.Thing) { num1 += 10f; } if (searcher.LastAttackedTarget == (LocalTargetInfo)target.Thing && Find.TickManager.TicksGame - searcher.LastAttackTargetTick <= 300) { num1 += 40f; } float num2 = num1 - CoverUtility.CalculateOverallBlockChance((LocalTargetInfo)target.Thing.Position, searcher.Thing.Position, searcher.Thing.Map) * 10f; if (target is Pawn pawn && pawn.RaceProps.Animal && (pawn.Faction != null && !pawn.IsFighting())) { num2 -= 50f; } return((num2 + FriendlyFireBlastRadiusTargetScoreOffset(target, searcher, verb) + FriendlyFireConeTargetScoreOffset(target, searcher, verb)) * target.TargetPriorityFactor); }
public IActorTask GetCurrentTask() { // На каждом шаге осматриваем окрестности // напредмет нарушителей. var intruders = CheckForIntruders(); var nearbyIntruder = intruders.FirstOrDefault(); if (nearbyIntruder != null) { _mode = PatrolMode.Pursuit; _targetIntruder = nearbyIntruder; _idleTask = null; _patrolPointIndex = null; } else if (_idleTask?.IsComplete == true) { _mode = PatrolMode.Bypass; _targetIntruder = null; _idleTask = null; } switch (_mode) { case PatrolMode.Bypass: return(HandleBypassMode()); case PatrolMode.Pursuit: return(HandlePersiutMode()); case PatrolMode.Idle: return(HandleIdleMode()); default: throw new InvalidOperationException($"Неизвестный режим патруллирования {_mode}"); } }
protected override Job TryGiveJob(Pawn pawn) { float num = float.MaxValue; Thing thing = null; List <IAttackTarget> potentialTargetsFor = pawn.Map.attackTargetsCache.GetPotentialTargetsFor(pawn); for (int i = 0; i < potentialTargetsFor.Count; i++) { IAttackTarget attackTarget = potentialTargetsFor[i]; if (!attackTarget.ThreatDisabled(pawn)) { Thing thing2 = (Thing)attackTarget; int num2 = thing2.Position.DistanceToSquared(pawn.Position); if ((float)num2 < num && pawn.CanReach(thing2, PathEndMode.OnCell, Danger.Deadly, false, TraverseMode.ByPawn)) { num = (float)num2; thing = thing2; } } } Job result; if (thing != null) { result = new Job(JobDefOf.Goto, thing) { checkOverrideOnExpire = true, expiryInterval = 500, collideWithPawns = true }; } else { result = null; } return(result); }
public void StartAttacking(IAttackTarget attackTarget, object locker) { IsAttacking = true; var attackCooldown = Convert.ToInt32(1000 / Monster.AttackSpeed); while (IsAttacking) { Thread.Sleep(attackCooldown); lock (locker) { if (Monster.IsDead || attackTarget.IsDead) { break; } var dealtDamage = AttackManager.Attack(attackTarget); if (attackTarget.IsDead) { break; } } } }
private static float FriendlyFireConeTargetScoreOffset(IAttackTarget target, IAttackTargetSearcher searcher, Verb verb) { if (!(searcher.Thing is Pawn pawn)) { return(0f); } if (pawn.RaceProps.intelligence < Intelligence.ToolUser) { return(0f); } if (pawn.RaceProps.IsMechanoid) { return(0f); } if (!(verb is Verb_Shoot verb_Shoot)) { return(0f); } ThingDef defaultProjectile = verb_Shoot.verbProps.defaultProjectile; if (defaultProjectile == null) { return(0f); } if (defaultProjectile.projectile.flyOverhead) { return(0f); } Map map = pawn.Map; ShotReport report = ShotReport.HitReportFor(pawn, verb, (Thing)target); float a = VerbUtility.CalculateAdjustedForcedMiss(verb.verbProps.forcedMissRadius, report.ShootLine.Dest - report.ShootLine.Source); float radius = Mathf.Max(a, 1.5f); IntVec3 dest2 = report.ShootLine.Dest; IEnumerable <IntVec3> source = from dest in GenRadial.RadialCellsAround(dest2, radius, true) where dest.InBounds(map) select dest; IEnumerable <ShootLine> source2 = from dest in source select new ShootLine(report.ShootLine.Source, dest); IEnumerable <IntVec3> source3 = source2.SelectMany((ShootLine line) => line.Points().Concat(line.Dest).TakeWhile((IntVec3 pos) => pos.CanBeSeenOverFast(map))); IEnumerable <IntVec3> enumerable = source3.Distinct <IntVec3>(); float num = 0f; foreach (IntVec3 c in enumerable) { float num2 = VerbUtility.InterceptChanceFactorFromDistance(report.ShootLine.Source.ToVector3Shifted(), c); if (num2 > 0f) { List <Thing> thingList = c.GetThingList(map); for (int i = 0; i < thingList.Count; i++) { Thing thing = thingList[i]; if (thing is IAttackTarget && thing != target) { float num3; if (thing == searcher) { num3 = 40f; } else if (thing is Pawn) { num3 = ((!thing.def.race.Animal) ? 18f : 7f); } else { num3 = 10f; } num3 *= num2; if (searcher.Thing.HostileTo(thing)) { num3 *= 0.6f; } else { num3 *= -1f; } num += num3; } } } } return(num); }
private static bool CanShootAtFromCurrentPosition(IAttackTarget target, IAttackTargetSearcher searcher, Verb verb) { return(verb != null && verb.CanHitTargetFrom(searcher.Thing.Position, target.Thing)); }
private static IAttackTarget FindBestReachableMeleeTarget(Predicate <IAttackTarget> validator, Pawn searcherPawn, float maxTargDist, bool canBash) { maxTargDist = Mathf.Min(maxTargDist, 30f); IAttackTarget reachableTarget = null; IAttackTarget bestTargetOnCell(IntVec3 x) { List <Thing> thingList = x.GetThingList(searcherPawn.Map); for (int i = 0; i < thingList.Count; i++) { Thing thing = thingList[i]; if (thing is IAttackTarget attackTarget) { if (validator(attackTarget)) { if (ReachabilityImmediate.CanReachImmediate(x, thing, searcherPawn.Map, PathEndMode.Touch, searcherPawn)) { if (searcherPawn.CanReachImmediate(thing, PathEndMode.Touch) || searcherPawn.Map.attackTargetReservationManager.CanReserve(searcherPawn, attackTarget)) { return(attackTarget); } } } } } return(null); } searcherPawn.Map.floodFiller.FloodFill(searcherPawn.Position, delegate(IntVec3 x) { if (!x.Walkable(searcherPawn.Map)) { return(false); } if ((float)x.DistanceToSquared(searcherPawn.Position) > maxTargDist * maxTargDist) { return(false); } if (!canBash) { if (x.GetEdifice(searcherPawn.Map) is Building_Door building_Door && !building_Door.CanPhysicallyPass(searcherPawn)) { return(false); } } return(!PawnUtility.AnyPawnBlockingPathAt(x, searcherPawn, true, false, false)); }, delegate(IntVec3 x) { for (int i = 0; i < 8; i++) { IntVec3 intVec = x + GenAdj.AdjacentCells[i]; if (intVec.InBounds(searcherPawn.Map)) { IAttackTarget attackTarget = bestTargetOnCell(intVec); if (attackTarget != null) { reachableTarget = attackTarget; break; } } } return(reachableTarget != null); }, int.MaxValue, false, null); return(reachableTarget); }
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); }
private static float FriendlyFireConeTargetScoreOffset(IAttackTarget target, IAttackTargetSearcher searcher, Verb verb) { Pawn pawn = searcher.Thing as Pawn; if (pawn == null) { return(0f); } if ((int)pawn.RaceProps.intelligence < 1) { return(0f); } if (pawn.RaceProps.IsMechanoid) { return(0f); } Verb_Shoot verb_Shoot = verb as Verb_Shoot; if (verb_Shoot == null) { return(0f); } ThingDef defaultProjectile = verb_Shoot.verbProps.defaultProjectile; if (defaultProjectile == null) { return(0f); } if (defaultProjectile.projectile.flyOverhead) { return(0f); } Map map = pawn.Map; ShotReport report = ShotReport.HitReportFor(pawn, verb, (Thing)target); float radius = Mathf.Max(VerbUtility.CalculateAdjustedForcedMiss(verb.verbProps.forcedMissRadius, report.ShootLine.Dest - report.ShootLine.Source), 1.5f); IEnumerable <IntVec3> enumerable = (from dest in GenRadial.RadialCellsAround(report.ShootLine.Dest, radius, useCenter: true) where dest.InBounds(map) select new ShootLine(report.ShootLine.Source, dest)).SelectMany((ShootLine line) => line.Points().Concat(line.Dest).TakeWhile((IntVec3 pos) => pos.CanBeSeenOverFast(map))).Distinct(); float num = 0f; foreach (IntVec3 item in enumerable) { float num2 = VerbUtility.InterceptChanceFactorFromDistance(report.ShootLine.Source.ToVector3Shifted(), item); if (!(num2 <= 0f)) { List <Thing> thingList = item.GetThingList(map); for (int i = 0; i < thingList.Count; i++) { Thing thing = thingList[i]; if (thing is IAttackTarget && thing != target) { float num3 = (thing == searcher) ? 40f : ((!(thing is Pawn)) ? 10f : (thing.def.race.Animal ? 7f : 18f)); num3 *= num2; num3 = ((!searcher.Thing.HostileTo(thing)) ? (num3 * -1f) : (num3 * 0.6f)); num += num3; } } } } return(num); }
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 void ReleaseAllForTarget(IAttackTarget target) { reservations.RemoveAll((AttackTargetReservation x) => x.target == target); }
/// <summary> /// Best attack target for VehicleTurret /// </summary> /// <param name="cannon"></param> /// <param name="flags"></param> /// <param name="validator"></param> /// <param name="minDist"></param> /// <param name="maxDist"></param> /// <param name="locus"></param> /// <param name="maxTravelRadiusFromLocus"></param> /// <param name="canBash"></param> /// <param name="canTakeTargetsCloserThanEffectiveMinRange"></param> /// <returns></returns> public static IAttackTarget BestAttackTarget(VehicleTurret cannon, TargetScanFlags flags, Predicate <Thing> validator = null, float minDist = 0f, float maxDist = 9999f, IntVec3 locus = default(IntVec3), float maxTravelRadiusFromLocus = 3.4028235E+38f, bool canBash = false, bool canTakeTargetsCloserThanEffectiveMinRange = true) { VehiclePawn searcherPawn = cannon.vehicle; float minDistSquared = minDist * minDist; float num = maxTravelRadiusFromLocus + cannon.MaxRange; float maxLocusDistSquared = num * num; Func <IntVec3, bool> losValidator = null; if ((flags & TargetScanFlags.LOSBlockableByGas) != TargetScanFlags.None) { losValidator = delegate(IntVec3 vec3) { Gas gas = vec3.GetGas(searcherPawn.Map); return(gas == null || !gas.def.gas.blockTurretTracking); }; } Predicate <IAttackTarget> innerValidator = delegate(IAttackTarget t) { Thing thing = t.Thing; if (t == searcherPawn) { return(false); } if (minDistSquared > 0f && (float)(searcherPawn.Position - thing.Position).LengthHorizontalSquared < minDistSquared) { return(false); } if (!canTakeTargetsCloserThanEffectiveMinRange) { float num2 = cannon.MinRange; if (num2 > 0f && (float)(cannon.vehicle.Position - thing.Position).LengthHorizontalSquared < num2 * num2) { return(false); } } if (maxTravelRadiusFromLocus < 9999f && (thing.Position - locus).LengthHorizontalSquared > maxLocusDistSquared) { return(false); } if (!searcherPawn.HostileTo(thing)) { return(false); } if (validator != null && !validator(thing)) { return(false); } if ((flags & TargetScanFlags.NeedLOSToAll) != TargetScanFlags.None) { if (losValidator != null && (!losValidator(searcherPawn.Position) || !losValidator(thing.Position))) { return(false); } if (!searcherPawn.CanSee(thing, losValidator)) { if (t is Pawn) { if ((flags & TargetScanFlags.NeedLOSToPawns) != TargetScanFlags.None) { return(false); } } else if ((flags & TargetScanFlags.NeedLOSToNonPawns) != TargetScanFlags.None) { return(false); } } } if (((flags & TargetScanFlags.NeedThreat) != TargetScanFlags.None || (flags & TargetScanFlags.NeedAutoTargetable) != TargetScanFlags.None) && t.ThreatDisabled(searcherPawn)) { return(false); } if ((flags & TargetScanFlags.NeedAutoTargetable) != TargetScanFlags.None && !AttackTargetFinder.IsAutoTargetable(t)) { return(false); } if ((flags & TargetScanFlags.NeedActiveThreat) != TargetScanFlags.None && !GenHostility.IsActiveThreatTo(t, searcherPawn.Faction)) { return(false); } Pawn pawn = t as Pawn; if ((flags & TargetScanFlags.NeedNonBurning) != TargetScanFlags.None && thing.IsBurning()) { 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; using (CellRect.Enumerator enumerator = thing.OccupiedRect().GetEnumerator()) { while (enumerator.MoveNext()) { if (!enumerator.Current.Fogged(thing.Map)) { flag2 = true; break; } } } if (!flag2) { return(false); } } return(true); }; List <IAttackTarget> tmpTargets = new List <IAttackTarget>(); tmpTargets.AddRange(searcherPawn.Map.attackTargetsCache.GetPotentialTargetsFor(searcherPawn)); bool flag = false; for (int i = 0; i < tmpTargets.Count; i++) { IAttackTarget attackTarget = tmpTargets[i]; if (attackTarget.Thing.Position.InHorDistOf(searcherPawn.Position, maxDist) && innerValidator(attackTarget) && VehicleTurret.TryFindShootLineFromTo(searcherPawn.Position, new LocalTargetInfo(attackTarget.Thing), out ShootLine resultingLine)) { flag = true; break; } } IAttackTarget result; if (flag) { tmpTargets.RemoveAll((IAttackTarget x) => !x.Thing.Position.InHorDistOf(searcherPawn.Position, maxDist) || !innerValidator(x)); result = GetRandomShootingTargetByScore(tmpTargets, searcherPawn); } else { Predicate <Thing> validator2; if ((flags & TargetScanFlags.NeedReachableIfCantHitFromMyPos) != TargetScanFlags.None && (flags & TargetScanFlags.NeedReachable) == TargetScanFlags.None) { validator2 = ((Thing t) => innerValidator((IAttackTarget)t) && VehicleTurret.TryFindShootLineFromTo(searcherPawn.Position, new LocalTargetInfo(t), out ShootLine resultingLine)); } else { validator2 = ((Thing t) => innerValidator((IAttackTarget)t)); } result = (IAttackTarget)GenClosest.ClosestThing_Global(searcherPawn.Position, tmpTargets, maxDist, validator2, null); } tmpTargets.Clear(); return(result); }