// Token: 0x06000420 RID: 1056 RVA: 0x0002CD30 File Offset: 0x0002B130 protected override IntVec3 GetWanderRoot(Pawn pawn) { if (pawn.isXenomorph()) { HiveLike hivelike = pawn.mindState.duty != null && pawn.mindState.duty.focus != null ? pawn.mindState.duty.focus.Thing as HiveLike : null; if (hivelike != null) { return(hivelike.Position); } /* * if (hivelike==null) * { * hivelike = FindClosestHiveLike(pawn); * } */ if (hivelike == null || !hivelike.Spawned) { if (XenomorphUtil.HivelikesPresent(pawn.Map)) { return(XenomorphUtil.ClosestReachableHivelike(pawn).Position); } if (!XenomorphKidnapUtility.hiveslimepresent) { if (XenomorphKidnapUtility.TryFindGoodHiveLoc(pawn, out IntVec3 c)) { return(c); } } else if (!XenomorphUtil.ClosestReachableHiveSlime(pawn).DestroyedOrNull()) { return(XenomorphUtil.ClosestReachableHiveSlime(pawn).Position); } return(pawn.Position); } // Log.Message(string.Format("JobGiver_WanderHiveLike hivelike.Position: {0}", hivelike.Position)); return(hivelike.Position); } else if (pawn.isNeomorph()) { Corpse corpse = (Corpse)GenClosest.ClosestThingReachable(pawn.Position, pawn.Map, ThingRequest.ForGroup(ThingRequestGroup.Corpse), PathEndMode.Touch, TraverseParms.For(pawn, Danger.Deadly), 20f); if (corpse != null) { return(corpse.Position); } return(pawn.Position); } else { return(pawn.Position); } }
public static bool TryFindBestItemToSteal(IntVec3 root, Map map, float maxDist, out Thing item, Pawn thief, List <Thing> disallowed = null) { if (thief != null && !thief.health.capacities.CapableOf(PawnCapacityDefOf.Manipulation)) { item = null; return(false); } if ((thief != null && !map.reachability.CanReachMapEdge(thief.Position, TraverseParms.For(thief, Danger.Some, TraverseMode.ByPawn, false))) || (thief == null && !map.reachability.CanReachMapEdge(root, TraverseParms.For(TraverseMode.PassDoors, Danger.Some, false)))) { item = null; return(false); } Predicate <Thing> validator = (Thing t) => (thief == null || thief.CanReserve(t, 1, -1, null, false)) && (disallowed == null || !disallowed.Contains(t)) && t.def.stealable && !t.IsBurning(); item = GenClosest.ClosestThing_Regionwise_ReachablePrioritized(root, map, ThingRequest.ForGroup(ThingRequestGroup.HaulableEverOrMinifiable), PathEndMode.ClosestTouch, TraverseParms.For(TraverseMode.NoPassClosedDoors, Danger.Some, false), maxDist, validator, new Func <Thing, float>(StealAIUtility.GetValue), 15, 15); if (item != null && StealAIUtility.GetValue(item) < 320f) { item = null; } return(item != null); }
private static bool TryFindBestBillIngredients(Bill bill, Pawn pawn, Thing billGiver, List <ThingCount> chosen) { // 最終結果クリア chosen.Clear(); // 中間結果クリア newRelevantThings.Clear(); // そもそも材料不要 if (bill.recipe.ingredients.Count == 0) { return(true); } // 作業位置 var rootCell = GetBillGiverRootCell(billGiver, pawn); // リージョン取得 Region rootReg = rootCell.GetRegion(pawn.Map, RegionType.Set_Passable); if (rootReg == null) { return(false); } // 素材を順番に並べて取得(任意材料、固定材料、その他) MakeIngredientsListInProcessingOrder(ingredientsOrdered, bill); // 中間結果クリア relevantThings.Clear(); processedThings.Clear(); bool foundAll = false; // 材料の基本探索条件 Predicate <Thing> baseValidator = (t) => { return(t.Spawned && // スポーン済み !t.IsForbidden(pawn) && // 禁止されていない (float)(t.Position - billGiver.Position).LengthHorizontalSquared < bill.ingredientSearchRadius * bill.ingredientSearchRadius && // billごとの材料探索範囲以内 bill.IsFixedOrAllowedIngredient(t) && // billとして許可された材料である bill.recipe.ingredients.Any((ingNeed) => ingNeed.filter.Allows(t)) && // レシピとして許可された材料である pawn.CanReserve(t)); // 予約可能 }; TraverseParms traverseParams = TraverseParms.For(pawn); RegionEntryPredicate entryCondition = (from, r) => r.Allows(traverseParams, false); int adjacentRegionsAvailable = rootReg.Neighbors.Count((region) => entryCondition(rootReg, region)); int regionsProcessed = 0; // ??? processedThings.AddRange(relevantThings); RegionProcessor regionProcessor = (r) => { // 運搬可能な物ループ foreach (var thing in r.ListerThings.ThingsMatching(ThingRequest.ForGroup(ThingRequestGroup.HaulableEver))) { // 既に含まれている物は無視 if (processedThings.Contains(thing)) { continue; } // そのリージョンからその物にタッチしに行けるか if (!ReachabilityWithinRegion.ThingFromRegionListerReachable(thing, r, PathEndMode.ClosestTouch, pawn)) { continue; } // 基本条件を満足しない場合はダメ if (!baseValidator(thing)) { continue; } // リストに加える newRelevantThings.Add(thing); processedThings.Add(thing); } regionsProcessed++; if (newRelevantThings.Count > 0 && regionsProcessed > adjacentRegionsAvailable) { // 二つの物の距離を比べる Comparison <Thing> comparison = (t1, t2) => { float t1dist = (float)(t1.Position - rootCell).LengthHorizontalSquared; float t2dist = (float)(t2.Position - rootCell).LengthHorizontalSquared; return(t1dist.CompareTo(t2dist)); }; // 距離の昇順?にソート newRelevantThings.Sort(comparison); // 探索した素材を追加 relevantThings.AddRange(newRelevantThings); // 新しく探索した素材リストをクリア newRelevantThings.Clear(); // 素材リストの中から最適な素材を見つける if (TryFindBestBillIngredientsInSet(relevantThings, bill, chosen)) { // 全部見つかった foundAll = true; return(true); } } // 全部は見つからなかった return(false); }; RegionTraverser.BreadthFirstTraverse(rootReg, entryCondition, regionProcessor); relevantThings.Clear(); newRelevantThings.Clear(); return(foundAll); }
static bool Prefix(Pawn eater, Pawn getter, bool allowPlant, bool allowForbidden, bool desperate, FoodPreferability maxPref, bool allowCorpse, bool allowDrug, out ThingDef foodDef, ref Thing __result) { foodDef = null; if (eater == null || eater.Faction == null || !eater.Faction.IsPlayer || eater.def.race.Humanlike) { return(true); } Comp_PawnMenu comp = eater.GetComp <Comp_PawnMenu>(); if (comp == null) { return(true); } if (!comp.activated()) { return(true); } FoodPreferability minPref = FoodPreferability.NeverForNutrition; Predicate <Thing> foodValidator = delegate(Thing t) { if (!allowForbidden && t.IsForbidden(getter)) { return(false); } if (t.def.ingestible.preferability < minPref) { return(false); } if (t.def.ingestible.preferability > maxPref) { return(false); } if (!t.IngestibleNow || !t.def.IsNutritionGivingIngestible || (!allowCorpse && t is Corpse) || (!allowDrug && t.def.IsDrug) || (!desperate && t.IsNotFresh()) || t.IsDessicated() || !eater.RaceProps.WillAutomaticallyEat(t) || !getter.AnimalAwareOf(t) || !getter.CanReserve(t, 1, -1, null, false)) { return(false); } return(comp.contains(t.def)); }; ThingRequest thingRequest; if ((eater.RaceProps.foodType & (FoodTypeFlags.Plant | FoodTypeFlags.Tree)) != FoodTypeFlags.None && allowPlant) { thingRequest = ThingRequest.ForGroup(ThingRequestGroup.FoodSource); } else { thingRequest = ThingRequest.ForGroup(ThingRequestGroup.FoodSourceNotPlantOrTree); } int searchRegionsMax = 100; HashSet <Thing> ___filtered = new HashSet <Thing>(); foreach (Thing thing2 in GenRadial.RadialDistinctThingsAround(getter.Position, getter.Map, 2f, true)) { Pawn pawn = thing2 as Pawn; if (pawn != null && pawn != getter && pawn.RaceProps.Animal && pawn.CurJob != null && pawn.CurJob.def == JobDefOf.Ingest && pawn.CurJob.GetTarget(TargetIndex.A).HasThing) { ___filtered.Add(pawn.CurJob.GetTarget(TargetIndex.A).Thing); } } bool ignoreEntirelyForbiddenRegions = !allowForbidden && ForbidUtility.CaresAboutForbidden(getter, true) && getter.playerSettings != null && getter.playerSettings.EffectiveAreaRestrictionInPawnCurrentMap != null; Predicate <Thing> predicate = (Thing t) => foodValidator(t) && !___filtered.Contains(t) && !t.IsNotFresh(); IntVec3 position = getter.Position; Map map = getter.Map; PathEndMode peMode = PathEndMode.ClosestTouch; TraverseParms traverseParams = TraverseParms.For(getter, Danger.Deadly, TraverseMode.ByPawn, false); Thing bestThing = GenClosest.ClosestThingReachable(position, map, thingRequest, peMode, traverseParams, 9999f, predicate, null, 0, searchRegionsMax, false, RegionType.Set_Passable, ignoreEntirelyForbiddenRegions); if (bestThing != null) { if (bestThing != null) { foodDef = FoodUtility.GetFinalIngestibleDef(bestThing, false); } __result = bestThing; return(false); } return(true); }
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); }
public static Building_GuestBed FindBedFor(this Pawn pawn) { Predicate <Thing> bedValidator = delegate(Thing t) { if (!(t is Building_GuestBed)) { return(false); } if (!pawn.CanReserveAndReach(t, PathEndMode.OnCell, Danger.Some)) { return(false); } var b = (Building_GuestBed)t; if (b.CurOccupant != null) { return(false); } if (b.ForPrisoners) { return(false); } Find.Maps.ForEach(m => m.reservationManager.ReleaseAllForTarget(b)); // TODO: Put this somewhere smarter return(!b.IsForbidden(pawn) && !b.IsBurning()); }; var bed = (Building_GuestBed)GenClosest.ClosestThingReachable(pawn.GetLord().CurLordToil.FlagLoc, pawn.MapHeld, ThingRequest.ForGroup(ThingRequestGroup.BuildingArtificial), PathEndMode.OnCell, TraverseParms.For(pawn), 500f, bedValidator); return(bed); }
public static Toil CheckForGetOpportunityDuplicate(Toil getHaulTargetToil, TargetIndex haulableInd, TargetIndex storeCellInd, bool takeFromValidStorage = false, Predicate <Thing> extraValidator = null) { Toil toil = new Toil(); toil.initAction = delegate { Pawn actor = toil.actor; Job curJob = actor.jobs.curJob; if (actor.carryTracker.CarriedThing.def.stackLimit != 1 && !actor.carryTracker.Full && curJob.count > 0) { Thing thing = null; Predicate <Thing> validator = delegate(Thing t) { if (!t.Spawned) { return(false); } if (t.def != actor.carryTracker.CarriedThing.def) { return(false); } if (!t.CanStackWith(actor.carryTracker.CarriedThing)) { return(false); } if (t.IsForbidden(actor)) { return(false); } if (!takeFromValidStorage && t.IsInValidStorage()) { return(false); } if (storeCellInd != 0 && !curJob.GetTarget(storeCellInd).Cell.IsValidStorageFor(actor.Map, t)) { return(false); } if (!actor.CanReserve(t)) { return(false); } return((extraValidator == null || extraValidator(t)) ? true : false); }; thing = GenClosest.ClosestThingReachable(actor.Position, actor.Map, ThingRequest.ForGroup(ThingRequestGroup.HaulableAlways), PathEndMode.ClosestTouch, TraverseParms.For(actor), 8f, validator); if (thing != null) { curJob.SetTarget(haulableInd, thing); actor.jobs.curDriver.JumpToToil(getHaulTargetToil); } } }; return(toil); }
public static Toil CarryIngestibleToChewSpot(Pawn pawn, TargetIndex ingestibleInd) { Toil toil = new Toil(); toil.initAction = delegate { Pawn actor = toil.actor; IntVec3 intVec = IntVec3.Invalid; Thing thing = null; Thing thing2 = actor.CurJob.GetTarget(ingestibleInd).Thing; Predicate <Thing> baseChairValidator = delegate(Thing t) { if (t.def.building != null && t.def.building.isSittable) { if (t.IsForbidden(pawn)) { return(false); } if (!actor.CanReserve(t, 1, -1, null, false)) { return(false); } if (!t.IsSociallyProper(actor)) { return(false); } if (t.IsBurning()) { return(false); } if (t.HostileTo(pawn)) { return(false); } bool flag = false; for (int i = 0; i < 4; i++) { IntVec3 c = t.Position + GenAdj.CardinalDirections[i]; Building edifice = c.GetEdifice(t.Map); if (edifice != null && edifice.def.surfaceType == SurfaceType.Eat) { flag = true; break; } } if (!flag) { return(false); } return(true); } return(false); }; if (thing2.def.ingestible.chairSearchRadius > 0.0) { thing = GenClosest.ClosestThingReachable(actor.Position, actor.Map, ThingRequest.ForGroup(ThingRequestGroup.BuildingArtificial), PathEndMode.OnCell, TraverseParms.For(actor, Danger.Deadly, TraverseMode.ByPawn, false), thing2.def.ingestible.chairSearchRadius, (Thing t) => baseChairValidator(t) && t.Position.GetDangerFor(pawn, t.Map) == Danger.None, null, 0, -1, false, RegionType.Set_Passable, false); } if (thing == null) { intVec = RCellFinder.SpotToChewStandingNear(actor, actor.CurJob.GetTarget(ingestibleInd).Thing); Danger chewSpotDanger = intVec.GetDangerFor(pawn, actor.Map); if (chewSpotDanger != Danger.None) { thing = GenClosest.ClosestThingReachable(actor.Position, actor.Map, ThingRequest.ForGroup(ThingRequestGroup.BuildingArtificial), PathEndMode.OnCell, TraverseParms.For(actor, Danger.Deadly, TraverseMode.ByPawn, false), thing2.def.ingestible.chairSearchRadius, (Thing t) => baseChairValidator(t) && (int)t.Position.GetDangerFor(pawn, t.Map) <= (int)chewSpotDanger, null, 0, -1, false, RegionType.Set_Passable, false); } } if (thing != null) { intVec = thing.Position; actor.Reserve(thing, actor.CurJob, 1, -1, null); } actor.Map.pawnDestinationReservationManager.Reserve(actor, actor.CurJob, intVec); actor.pather.StartPath(intVec, PathEndMode.OnCell); }; toil.defaultCompleteMode = ToilCompleteMode.PatherArrival; return(toil); }
protected override Job TryGiveJob(Pawn pawn) { Predicate <Thing> validator = delegate(Thing t) { Pawn pawn3 = (Pawn)t; return((pawn3.Downed && pawn3.Faction == pawn.Faction && !pawn3.InBed() && pawn.CanReserve(pawn3) && !pawn3.IsForbidden(pawn) && !GenAI.EnemyIsNear(pawn3, 25f)) ? true : false); }; Pawn pawn2 = (Pawn)GenClosest.ClosestThingReachable(pawn.Position, pawn.Map, ThingRequest.ForGroup(ThingRequestGroup.Pawn), PathEndMode.OnCell, TraverseParms.For(pawn), radius, validator); if (pawn2 == null) { return(null); } Building_Bed building_Bed = RestUtility.FindBedFor(pawn2, pawn, pawn2.HostFaction == pawn.Faction, checkSocialProperness: false); if (building_Bed == null || !pawn2.CanReserve(building_Bed)) { return(null); } Job job = JobMaker.MakeJob(JobDefOf.Rescue, pawn2, building_Bed); job.count = 1; return(job); }
public static Building_Bed FindPatientBedFor(Pawn pawn) { Predicate <Thing> medBedValidator = delegate(Thing t) { Building_Bed building_Bed2 = t as Building_Bed; if (building_Bed2 == null) { return(false); } if (!building_Bed2.Medical && building_Bed2.def.building.bed_humanlike) { return(false); } if (!RestUtility.IsValidBedFor(building_Bed2, pawn, pawn, pawn.IsPrisoner, false, true, false)) { return(false); } return(true); }; if (pawn.InBed() && medBedValidator(pawn.CurrentBed())) { return(pawn.CurrentBed()); } for (int i = 0; i < 2; i++) { Danger maxDanger = (Danger)((i == 0) ? 1 : 3); Building_Bed building_Bed = (Building_Bed)GenClosest.ClosestThingReachable(pawn.Position, pawn.Map, ThingRequest.ForGroup(ThingRequestGroup.BuildingArtificial), PathEndMode.OnCell, TraverseParms.For(pawn, Danger.Deadly, TraverseMode.ByPawn, false), 9999f, (Thing b) => (int)b.Position.GetDangerFor(pawn, pawn.Map) <= (int)maxDanger && medBedValidator(b), null, 0, -1, false, RegionType.Set_Passable, false); if (building_Bed != null) { return(building_Bed); } } return(RestUtility.FindBedFor(pawn)); }
// Token: 0x0600001A RID: 26 RVA: 0x0000247C File Offset: 0x0000067C protected override Job TryGiveJob(Pawn pawn) { bool downed = pawn.Downed; Job result; if (downed) { result = null; } else { Need_Energy need_Energy = pawn.needs.TryGetNeed <Need_Energy>(); bool flag = need_Energy == null; if (flag) { result = null; } else { bool flag2 = need_Energy.CurLevelPercentage >= Need_Energy.rechargePercentage; if (flag2) { result = null; } else { Thing thing3 = GenClosest.ClosestThingReachable(pawn.Position, pawn.Map, ThingRequest.ForGroup(ThingRequestGroup.BuildingArtificial), PathEndMode.ClosestTouch, TraverseParms.For(pawn, Danger.Deadly, TraverseMode.ByPawn, false), 9999f, (Thing thing) => this.BestClosestPowerSource(pawn, thing), null, 0, -1, false, RegionType.Set_Passable, false); bool flag3 = thing3 != null; if (flag3) { Building building = thing3 as Building; bool flag4 = thing3 != null && building != null && building.PowerComp != null && building.PowerComp.PowerNet.CurrentStoredEnergy() > 50f; if (flag4) { IntVec3 position = thing3.Position; bool flag5 = position.Walkable(pawn.Map) && position.InAllowedArea(pawn) && pawn.CanReserve(new LocalTargetInfo(position), 1, -1, null, false) && pawn.CanReach(position, PathEndMode.OnCell, Danger.Deadly, false, TraverseMode.ByPawn); if (flag5) { return(new Job(JobDefOf.ChJAndroidRecharge, thing3)); } IEnumerable <IntVec3> source = GenAdj.CellsAdjacentCardinal(building); Func <IntVec3, float> < > 9__1; Func <IntVec3, float> keySelector; if ((keySelector = < > 9__1) == null) { keySelector = (< > 9__1 = ((IntVec3 selector) => selector.DistanceTo(pawn.Position))); } foreach (IntVec3 intVec in source.OrderByDescending(keySelector)) { bool flag6 = intVec.Walkable(pawn.Map) && intVec.InAllowedArea(pawn) && pawn.CanReserve(new LocalTargetInfo(intVec), 1, -1, null, false) && pawn.CanReach(intVec, PathEndMode.OnCell, Danger.Deadly, false, TraverseMode.ByPawn); if (flag6) { return(new Job(JobDefOf.ChJAndroidRecharge, thing3, intVec)); } } } } Thing thing2 = GenClosest.ClosestThingReachable(pawn.Position, pawn.Map, ThingRequest.ForGroup(ThingRequestGroup.HaulableEver), PathEndMode.ClosestTouch, TraverseParms.For(pawn, Danger.Deadly, TraverseMode.ByPawn, false), 9999f, (Thing thing) => thing.TryGetComp <EnergySourceComp>() != null && !thing.IsForbidden(pawn) && pawn.CanReserve(new LocalTargetInfo(thing), 1, -1, null, false) && thing.Position.InAllowedArea(pawn) && pawn.CanReach(new LocalTargetInfo(thing), PathEndMode.OnCell, Danger.Deadly, false, TraverseMode.ByPawn), null, 0, -1, false, RegionType.Set_Passable, false); bool flag7 = thing2 != null; if (flag7) { EnergySourceComp energySourceComp = thing2.TryGetComp <EnergySourceComp>(); bool flag8 = energySourceComp != null; if (flag8) { int num = (int)Math.Ceiling((double)((need_Energy.MaxLevel - need_Energy.CurLevel) / energySourceComp.EnergyProps.energyWhenConsumed)); bool flag9 = num > 0; if (flag9) { return(new Job(JobDefOf.ChJAndroidRechargeEnergyComp, new LocalTargetInfo(thing2)) { count = num }); } } } result = null; } } } return(result); }
public void TryToTakeDownedOrDeadPawn(List <Pawn> relatedPawns) { if (pawn.CurJobDef == JobDefOf.TakeDownedOrDeadPawn || pawn.IsColonist || pawn.MentalState == null || pawn.IsSlave()) { return; } if (pawn.MentalStateDef == MentalStateDefOf.PanicFlee) { const float maxSearchDistance = 20; IntVec3 exitCell; if (!RCellFinder.TryFindBestExitSpot(pawn, out exitCell, TraverseMode.ByPawn)) { return; } // First priority: find any downed humanlike what is related to this pawn Predicate <Thing> validator = delegate(Thing t) { Pawn pawn3 = t as Pawn; return(pawn3 != null && pawn3.RaceProps.Humanlike && pawn3.PawnListed(relatedPawns) && pawn3.Downed && pawn.CanReserve(pawn3)); }; Pawn pawn2 = (Pawn)GenClosest.ClosestThingReachable(pawn.Position, pawn.Map, ThingRequest.ForGroup(ThingRequestGroup.Pawn), PathEndMode.ClosestTouch, TraverseParms.For(pawn, Danger.Deadly, TraverseMode.ByPawn, false), maxSearchDistance, validator, null, 0, -1, false, RegionType.Set_Passable, false); if (pawn2 != null) { //Log.Message(pawn + " try start job TakeDownedOrDeadPawn to " + pawn2); Job takeDownedOrDeadPawn = new Job(JobDefOf.TakeDownedOrDeadPawn) { targetA = pawn2, targetB = exitCell, count = 1 }; pawn.jobs.StartJob(takeDownedOrDeadPawn, JobCondition.InterruptForced, null, true); return; } // Second priority: find any downed humanlike what is consists in pawn's faction validator = delegate(Thing t) { Pawn pawn3 = t as Pawn; return(pawn3 != null && pawn3.RaceProps.Humanlike && pawn3.Faction == pawn.Faction && pawn3.Downed && pawn.CanReserve(pawn3)); }; pawn2 = (Pawn)GenClosest.ClosestThingReachable(pawn.Position, pawn.Map, ThingRequest.ForGroup(ThingRequestGroup.Pawn), PathEndMode.ClosestTouch, TraverseParms.For(pawn, Danger.Deadly, TraverseMode.ByPawn, false), maxSearchDistance, validator, null, 0, -1, false, RegionType.Set_Passable, false); if (pawn2 != null) { //Log.Message(pawn + " try start job TakeDownedOrDeadPawn to " + pawn2); Job takeDownedOrDeadPawn = new Job(JobDefOf.TakeDownedOrDeadPawn) { targetA = pawn2, targetB = exitCell, count = 1 }; pawn.jobs.StartJob(takeDownedOrDeadPawn, JobCondition.InterruptForced, null, true); return; } // Third priority: find any dead humanlike what was related to this pawn validator = delegate(Thing t) { Corpse corpse = t as Corpse; return(corpse != null && corpse.InnerPawn != null && corpse.InnerPawn.RaceProps.Humanlike && corpse.InnerPawn.PawnListed(relatedPawns) && pawn.CanReserve(corpse)); }; Corpse corpse2 = (Corpse)GenClosest.ClosestThingReachable(pawn.Position, pawn.Map, ThingRequest.ForGroup(ThingRequestGroup.Corpse), PathEndMode.ClosestTouch, TraverseParms.For(pawn, Danger.Deadly, TraverseMode.ByPawn, false), maxSearchDistance, validator, null, 0, -1, false, RegionType.Set_Passable, false); if (corpse2 != null) { //Log.Message(pawn + " try start job TakeDownedOrDeadPawn to " + corpse2); Job takeDownedOrDeadPawn = new Job(JobDefOf.TakeDownedOrDeadPawn) { targetA = corpse2, targetB = exitCell, count = 1 }; pawn.jobs.StartJob(takeDownedOrDeadPawn, JobCondition.InterruptForced, null, true); return; } return; } // if (pawn.health.HasHediffsNeedingTend()) // { // float maxSearchDistance = 30 * pawn.health.capacities.GetLevel(PawnCapacityDefOf.Hearing); // List<Thing> allPawnsOfFactionOnMap = (List<Thing>)pawn.Map.mapPawns.FreeHumanlikesOfFaction(pawn.Faction); // List<Thing> allPawnsOfFactionInRange = AvaliUtility.FindAllThingsOnMapAtRange(pawn as Thing, null, typeof(Pawn), allPawnsOfFactionOnMap, maxSearchDistance, 9999, true, true); // // if (allPawnsOfFactionInRange.Count == 0) // { // if (!pawn.Downed) // { // // } // else return; // } // // Pawn pawn1 = null; // // for (int i = 0; i < allPawnsOfFactionInRange.Count; i++) // { // Pawn pawn2 = allPawnsOfFactionInRange[i] as Pawn; // if (pawn2 != null && pawn2 != pawn && pawn2.inventory.Contains(Thing)) // { // // } // } // // // // //// if (pawn.inventory.Contains(ThingMaker.MakeThing(RimWorld.ThingDefOf.MedicineIndustrial))) //// { //// //// } // // #region Выполнется только в случае если у pawn1 в инвентаре есть медикоменты и pawnMedicineSkillLevel/2 < pawn1MedicineSkillLevel // Predicate<Thing> validator = delegate(Thing t) // { // Pawn pawn1 = t as Pawn; // // if (pawn1 != null && pawn1 != pawn && // pawn1.RaceProps.Humanlike && pawn1.Faction == pawn.Faction && // pawn1.inventory.Contains()) // { // int pawnMedicineSkillLevel = pawn.GetSkillLevel(SkillDefOf.Medicine); // int pawn1MedicineSkillLevel = pawn1.GetSkillLevel(SkillDefOf.Medicine); // // if (pawnMedicineSkillLevel/2 < pawn1MedicineSkillLevel) // { // return pawn.CanReserve(pawn1) && pawn1.CanReserve(pawn); // } // } // // return false; // }; // Pawn pawn2 = (Pawn)GenClosest.ClosestThingReachable(pawn.Position, pawn.Map, ThingRequest.ForGroup(ThingRequestGroup.Pawn), PathEndMode.ClosestTouch, TraverseParms.For(pawn, Danger.Deadly, TraverseMode.ByPawn, false), maxSearchDistance, validator, null, 0, -1, false, RegionType.Set_Passable, false); // if (pawn2 != null) // { // Job tendDownedPawn = new Job(RimWorld.JobDefOf.TendPatient) // { // targetA = pawn, // count = 1 // }; // // pawn2.jobs.StartJob(tendDownedPawn, JobCondition.InterruptForced, null, true); // return; // } // #endregion // // #region Выполнется только в случае если у pawn1 в инвентаре есть медикоменты // validator = delegate(Thing t) // { // Pawn pawn1 = t as Pawn; // // if (pawn1 != null && pawn1.RaceProps.Humanlike && pawn1.Faction == pawn.Faction && pawn1.inventory.Contains()) // { // int pawnMedicineSkillLevel = pawn.GetSkillLevel(SkillDefOf.Medicine); // int pawn1MedicineSkillLevel = pawn1.GetSkillLevel(SkillDefOf.Medicine); // // if (pawnMedicineSkillLevel/2 < pawn1MedicineSkillLevel) // { // return pawn.CanReserve(pawn1) && pawn1.CanReserve(pawn); // } // } // // return false; // }; // pawn2 = (Pawn)GenClosest.ClosestThingReachable(pawn.Position, pawn.Map, ThingRequest.ForGroup(ThingRequestGroup.Pawn), PathEndMode.ClosestTouch, TraverseParms.For(pawn, Danger.Deadly, TraverseMode.ByPawn, false), maxSearchDistance, validator, null, 0, -1, false, RegionType.Set_Passable, false); // if (pawn2 != null) // { // Job tendDownedPawn = new Job(RimWorld.JobDefOf.TendPatient) // { // targetA = pawn, // count = 1 // }; // // pawn2.jobs.StartJob(tendDownedPawn, JobCondition.InterruptForced, null, true); // return; // } // #endregion // // // // // // validator = delegate(Thing t) // { // Pawn pawn1 = t as Pawn; // // if (pawn1 != null && pawn1.RaceProps.Humanlike && pawn1.Faction == pawn.Faction) // { // int pawnMedicineSkillLevel = pawn.GetSkillLevel(SkillDefOf.Medicine); // int pawn1MedicineSkillLevel = pawn1.GetSkillLevel(SkillDefOf.Medicine); // // if (pawnMedicineSkillLevel < pawn1MedicineSkillLevel) // { // return pawn.CanReserve(pawn1) && pawn1.CanReserve(pawn); // } // } // // return false; // }; // pawn2 = (Pawn)GenClosest.ClosestThingReachable(pawn.Position, pawn.Map, ThingRequest.ForGroup(ThingRequestGroup.Pawn), PathEndMode.ClosestTouch, TraverseParms.For(pawn, Danger.Deadly, TraverseMode.ByPawn, false), maxSearchDistance, validator, null, 0, -1, false, RegionType.Set_Passable, false); // if (pawn2 != null) // { // Job tendDownedPawn = new Job(RimWorld.JobDefOf.TendPatient) // { // targetA = pawn, // count = 1 // }; // // pawn2.jobs.StartJob(tendDownedPawn, JobCondition.InterruptForced, null, true); // return; // } // // // // // // if (pawn.Downed) // { // // } // else // { // // } // } }
private static bool TryFindBestBillIngredients(Bill bill, Pawn pawn, Thing billGiver, List <ThingCount> chosen) { chosen.Clear(); newRelevantThings.Clear(); if (bill.recipe.ingredients.Count == 0) { return(true); } IntVec3 rootCell = GetBillGiverRootCell(billGiver, pawn); Region rootReg = rootCell.GetRegion(pawn.Map); if (rootReg == null) { return(false); } MakeIngredientsListInProcessingOrder(ingredientsOrdered, bill); relevantThings.Clear(); processedThings.Clear(); bool foundAll = false; Predicate <Thing> baseValidator = (Thing t) => t.Spawned && !t.IsForbidden(pawn) && (float)(t.Position - billGiver.Position).LengthHorizontalSquared < bill.ingredientSearchRadius * bill.ingredientSearchRadius && bill.IsFixedOrAllowedIngredient(t) && bill.recipe.ingredients.Any((IngredientCount ingNeed) => ingNeed.filter.Allows(t)) && pawn.CanReserve(t); bool billGiverIsPawn = billGiver is Pawn; if (billGiverIsPawn) { AddEveryMedicineToRelevantThings(pawn, billGiver, relevantThings, baseValidator, pawn.Map); if (TryFindBestBillIngredientsInSet(relevantThings, bill, chosen)) { relevantThings.Clear(); ingredientsOrdered.Clear(); return(true); } } TraverseParms traverseParams = TraverseParms.For(pawn); RegionEntryPredicate entryCondition = (Region from, Region r) => r.Allows(traverseParams, isDestination: false); int adjacentRegionsAvailable = rootReg.Neighbors.Count((Region region) => entryCondition(rootReg, region)); int regionsProcessed = 0; processedThings.AddRange(relevantThings); RegionProcessor regionProcessor = delegate(Region r) { List <Thing> list = r.ListerThings.ThingsMatching(ThingRequest.ForGroup(ThingRequestGroup.HaulableEver)); for (int i = 0; i < list.Count; i++) { Thing thing = list[i]; if (!processedThings.Contains(thing) && ReachabilityWithinRegion.ThingFromRegionListerReachable(thing, r, PathEndMode.ClosestTouch, pawn) && baseValidator(thing) && (!thing.def.IsMedicine || !billGiverIsPawn)) { newRelevantThings.Add(thing); processedThings.Add(thing); } } regionsProcessed++; if (newRelevantThings.Count > 0 && regionsProcessed > adjacentRegionsAvailable) { Comparison <Thing> comparison = delegate(Thing t1, Thing t2) { float num = (t1.Position - rootCell).LengthHorizontalSquared; float value = (t2.Position - rootCell).LengthHorizontalSquared; return(num.CompareTo(value)); }; newRelevantThings.Sort(comparison); relevantThings.AddRange(newRelevantThings); newRelevantThings.Clear(); if (TryFindBestBillIngredientsInSet(relevantThings, bill, chosen)) { foundAll = true; return(true); } } return(false); }; RegionTraverser.BreadthFirstTraverse(rootReg, entryCondition, regionProcessor, 99999); relevantThings.Clear(); newRelevantThings.Clear(); processedThings.Clear(); ingredientsOrdered.Clear(); return(foundAll); }
//slightly modified version of Toils_Ingest.CarryIngestibleToChewSpot public static Toil CarryPuzzleToSpot(Pawn pawn, TargetIndex puzzleInd) { var toil = new Toil(); toil.initAction = delegate { Pawn actor = toil.actor; IntVec3 intVec = IntVec3.Invalid; Thing thing = null; Thing thing2 = actor.CurJob.GetTarget(puzzleInd).Thing; bool baseChairValidator(Thing t) { if (t.def.building == null || !t.def.building.isSittable) { return(false); } if (t.IsForbidden(pawn)) { return(false); } if (!actor.CanReserve(t, 1, -1, null, false)) { return(false); } if (!t.IsSociallyProper(actor)) { return(false); } if (t.IsBurning()) { return(false); } if (t.HostileTo(pawn)) { return(false); } var result = false; for (var i = 0; i < 4; i++) { IntVec3 c = t.Position + GenAdj.CardinalDirections[i]; Building edifice = c.GetEdifice(t.Map); if (edifice != null && edifice.def.surfaceType == SurfaceType.Eat) { result = true; break; } } return(result); } //if you can find a table with chair, great. If not, go to your room. thing = GenClosest.ClosestThingReachable(actor.Position, actor.Map, ThingRequest.ForGroup(ThingRequestGroup.BuildingArtificial), PathEndMode.OnCell, TraverseParms.For(actor), 30f, //"chair search radius" (Thing t) => baseChairValidator(t) && t.Position.GetDangerFor(pawn, t.Map) == Danger.None); if (thing == null) { if (pawn.ownership?.OwnedRoom != null) { (from c in pawn.ownership.OwnedRoom.Cells where c.Standable(pawn.Map) && !c.IsForbidden(pawn) && pawn.CanReserveAndReach(c, PathEndMode.OnCell, Danger.None) select c).TryRandomElement(out intVec); } } if (thing != null) { intVec = thing.Position; actor.Reserve(thing, actor.CurJob, 1, -1, null); } if (intVec == IntVec3.Invalid) { intVec = RCellFinder.SpotToChewStandingNear(pawn, thing2); } actor.Map.pawnDestinationReservationManager.Reserve(actor, actor.CurJob, intVec); actor.pather.StartPath(intVec, PathEndMode.OnCell); }; toil.defaultCompleteMode = ToilCompleteMode.PatherArrival; return(toil); }
public static Building_BaseMechanoidPlatform GetAvailableMechanoidPlatform(Pawn pawn, Pawn targetPawn) { return((Building_BaseMechanoidPlatform)GenClosest.ClosestThingReachable(targetPawn.Position, targetPawn.Map, ThingRequest.ForGroup(ThingRequestGroup.BuildingArtificial), PathEndMode.OnCell, TraverseParms.For(pawn, Danger.Deadly, TraverseMode.ByPawn, false), 9999f, delegate(Thing b) { if (b is Building_BaseMechanoidPlatform platform && !b.IsBurning() && !b.IsForbidden(targetPawn) && targetPawn.CanReserve(b) && (targetPawn.ownership.OwnedBed == null && !platform.CompAssignableToPawn.AssignedPawns.Any() || platform.CompAssignableToPawn.AssignedPawns.Contains(targetPawn))) { CompFlickable flickable = platform.TryGetComp <CompFlickable>(); if (flickable != null && !flickable.SwitchIsOn) { return false; } return true; } return false; })); }
public static bool TryMakePreToilReservations_Prefix(ThingComp __instance, Pawn selPawn, ref IEnumerable <FloatMenuOption> __result) { if (!(selPawn.WorkTypeIsDisabled(WorkTypeDefOf.Research) || selPawn.WorkTagIsDisabled(WorkTags.Intellectual)) && selPawn.CanReach(__instance.parent, PathEndMode.ClosestTouch, Danger.Some, false, TraverseMode.ByPawn) && selPawn.CanReserve(__instance.parent, 1, -1, null, false)) { List <FloatMenuOption> modified = new List <FloatMenuOption>(); Thing thing = GenClosest.ClosestThingReachable(selPawn.Position, selPawn.Map, ThingRequest.ForGroup(ThingRequestGroup.ResearchBench), PathEndMode.InteractionCell, TraverseParms.For(selPawn, Danger.Some, TraverseMode.ByPawn, false), 9999f, (Thing t) => t is Building_WorkTable && selPawn.CanReserve(t, 1, -1, null, false), null, 0, -1, false, RegionType.Set_Passable, false); Job job = null; if (thing != null) { job = JobMaker.MakeJob(JobDefOf.ApplyTechprint); job.targetA = thing; job.targetB = __instance.parent; job.targetC = thing.Position; } modified.Add(new FloatMenuOption("ApplyTechprint".Translate(__instance.parent.Label).CapitalizeFirst(), delegate() { if (job == null) { Messages.Message("MessageNoResearchBenchForTechprint".Translate(), MessageTypeDefOf.RejectInput, true); return; } selPawn.jobs.TryTakeOrderedJob(job, JobTag.Misc); }, MenuOptionPriority.Default, null, null, 0f, null, null)); __result = modified.AsEnumerable(); return(false); } return(true); }
public override IEnumerable <FloatMenuOption> CompFloatMenuOptions(Pawn selPawn) { JobFailReason.Clear(); if (this.parent.def.building != null || this.parent.def.category == ThingCategory.Building || shard == null || !Base.ThingIsPrintable(this.parent.def)) { yield break; } if (this.parent.IsForbidden(selPawn)) { JobFailReason.Is("CannotPrioritizeForbidden".Translate(this.parent.Label, this.parent)); } else if (!selPawn.health.capacities.CapableOf(PawnCapacityDefOf.Manipulation)) { JobFailReason.Is("Incapable".Translate()); } else if (selPawn.WorkTypeIsDisabled(Base.DefOf.DTechprinting) || selPawn.WorkTagIsDisabled(WorkTags.Intellectual)) { JobFailReason.Is("CannotPrioritizeWorkTypeDisabled".Translate(Base.DefOf.DTechprinting.gerundLabel)); } else if (selPawn.workSettings.GetPriority(Base.DefOf.DTechprinting) == 0) { JobFailReason.Is("CannotPrioritizeNotAssignedToWorkType".Translate(Base.DefOf.DTechprinting.gerundLabel)); } else if (!selPawn.CanReach(this.parent, PathEndMode.ClosestTouch, Danger.Some, false, TraverseMode.ByPawn)) { JobFailReason.Is("CannotReach".Translate(), null); } else if (!selPawn.CanReserve(this.parent, 1, -1, null, false)) { Pawn pawn = selPawn.Map.reservationManager.FirstRespectedReserver(this.parent, selPawn); if (pawn == null) { pawn = selPawn.Map.physicalInteractionReservationManager.FirstReserverOf(selPawn); } if (pawn != null) { JobFailReason.Is("ReservedBy".Translate(pawn.LabelShort, pawn), null); } else { JobFailReason.Is("Reserved".Translate(), null); } } int minAmountToGrab = Base.IsSingleAllowed(this.parent.def) ? 1 : Base.IsStackAllowed(this.parent.def, ShardMaker.stackSize) ? ShardMaker.stackSize : 0; if (minAmountToGrab == 0 || this.parent.stackCount < minAmountToGrab) { JobFailReason.Is("notEnoughToShard".Translate(), null); } if (JobFailReason.HaveReason) { yield return(new FloatMenuOption("CannotGenericWorkCustom".Translate("techprint") + ": " + JobFailReason.Reason.CapitalizeFirst(), null, MenuOptionPriority.Default, null, null, 0f, null, null)); JobFailReason.Clear(); yield break; } HaulAIUtility.PawnCanAutomaticallyHaul(selPawn, this.parent, true); Thing techPrinter = GenClosest.ClosestThingReachable(selPawn.Position, selPawn.Map, ThingRequest.ForGroup(ThingRequestGroup.BuildingArtificial), PathEndMode.InteractionCell, TraverseParms.For(selPawn, Danger.Deadly, TraverseMode.ByPawn, false), 9999f, (Thing thing) => thing.def == Base.DefOf.DTechprinter && selPawn.CanReserve(thing, 1, -1, null, false)); Job job = null; if (techPrinter != null) { IBillGiver billGiver = techPrinter as IBillGiver; if (billGiver == null) { Log.Error("Techprinter isn't bill giver"); yield break; } job = MakeShardingJob(selPawn, billGiver, minAmountToGrab); } yield return(new FloatMenuOption("turnIntoShards".Translate(ShardMaker.CalcNumShardsFor(this.parent), shard.LabelCap, this.parent.LabelCap).CapitalizeFirst(), delegate() { if (job == null) { Messages.Message("noTechprinterAvailable".Translate(), MessageTypeDefOf.RejectInput, true); return; } selPawn.jobs.TryTakeOrderedJob(job, JobTag.MiscWork); }, MenuOptionPriority.VeryLow, null, null, 0f, null, null)); yield break; }
protected override Job TryGiveJob(Pawn pawn) { //if (pawn.def != ThingDefOf.Avali) return null; if (pawn.IsColonist || pawn.MentalState == null) { return(null); } if (pawn.MentalState.def == null || pawn.MentalState.def != MentalStateDefOf.PanicFlee) { return(null); } IntVec3 exitCell; if (!RCellFinder.TryFindBestExitSpot(pawn, out exitCell, TraverseMode.ByPawn)) { return(null); } Hediff_AvaliBiology avaliBiologyHediff = pawn.health.hediffSet.GetHediffs <Hediff_AvaliBiology>().First(); Predicate <Thing> validator = null; Pawn pawn2 = null; if (avaliBiologyHediff != null) { // First priority: find any downed humanlike what is related to this pawn validator = delegate(Thing t) { Pawn pawn3 = t as Pawn; return(pawn3.RaceProps.Humanlike && pawn3.PawnListed(avaliBiologyHediff.packPawns) && pawn3.Downed && pawn.CanReserve(pawn3)); }; pawn2 = (Pawn)GenClosest.ClosestThingReachable(pawn.Position, pawn.Map, ThingRequest.ForGroup(ThingRequestGroup.Pawn), PathEndMode.ClosestTouch, TraverseParms.For(pawn, Danger.Deadly, TraverseMode.ByPawn, false), maxSearchDistance, validator, null, 0, -1, false, RegionType.Set_Passable, false); if (pawn2 != null) { return(new Job(JobDefOf.TakeDownedOrDeadPawn) { targetA = pawn2, targetB = exitCell, count = 1 }); } } // Second priority: find any downed humanlike what is consist in pawn faction validator = delegate(Thing t) { Pawn pawn3 = t as Pawn; return(pawn3.RaceProps.Humanlike && pawn3.Faction == pawn.Faction && pawn3.Downed && pawn.CanReserve(pawn3)); }; pawn2 = (Pawn)GenClosest.ClosestThingReachable(pawn.Position, pawn.Map, ThingRequest.ForGroup(ThingRequestGroup.Pawn), PathEndMode.ClosestTouch, TraverseParms.For(pawn, Danger.Deadly, TraverseMode.ByPawn, false), maxSearchDistance, validator, null, 0, -1, false, RegionType.Set_Passable, false); if (pawn2 != null) { return(new Job(JobDefOf.TakeDownedOrDeadPawn) { targetA = pawn2, targetB = exitCell, count = 1 }); } // Third priority: find any dead humanlike what was related to this pawn validator = delegate(Thing t) { Corpse corpse = t as Corpse; return(corpse != null && corpse.InnerPawn != null && corpse.InnerPawn.RaceProps.Humanlike && corpse.InnerPawn.PawnListed(avaliBiologyHediff.packPawns) && pawn.CanReserve(corpse)); }; Corpse corpse2 = (Corpse)GenClosest.ClosestThingReachable(pawn.Position, pawn.Map, ThingRequest.ForGroup(ThingRequestGroup.Corpse), PathEndMode.ClosestTouch, TraverseParms.For(pawn, Danger.Deadly, TraverseMode.ByPawn, false), maxSearchDistance, validator, null, 0, -1, false, RegionType.Set_Passable, false); if (corpse2 != null) { //Log.Message(pawn + " try start job TakeDownedOrDeadPawn to " + corpse2); Job takeDownedOrDeadPawn = new Job(JobDefOf.TakeDownedOrDeadPawn) { targetA = corpse2, targetB = exitCell, count = 1 }; } return(null); }
/** * Move few stepf srom dispenser to avoid clustering in a single cell */ public static Toil CarryIngestibleToChewSpot(Pawn pawn, TargetIndex ingestibleInd) { Toil toil = new Toil(); toil.initAction = delegate { Pawn actor = toil.actor; IntVec3 intVec = IntVec3.Invalid; Thing thing = null; Thing thing2 = actor.CurJob.GetTarget(ingestibleInd).Thing; intVec = RCellFinder.SpotToChewStandingNear(actor, actor.CurJob.GetTarget(ingestibleInd).Thing); Danger chewSpotDanger = intVec.GetDangerFor(pawn, actor.Map); if (chewSpotDanger != Danger.None) { thing = GenClosest.ClosestThingReachable(actor.Position, actor.Map, ThingRequest.ForGroup(ThingRequestGroup.BuildingArtificial), PathEndMode.OnCell, TraverseParms.For(actor), thing2.def.ingestible.chairSearchRadius, (Thing t) => (int)t.Position.GetDangerFor(pawn, t.Map) <= (int)chewSpotDanger); } if (thing != null) { intVec = thing.Position; actor.Reserve(thing, actor.CurJob); } actor.Map.pawnDestinationReservationManager.Reserve(actor, actor.CurJob, intVec); actor.pather.StartPath(intVec, PathEndMode.OnCell); }; toil.defaultCompleteMode = ToilCompleteMode.PatherArrival; return(toil); }
/// <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); } } }
/// <summary> /// Used by GetPrioritySlot, actually finds a requested thing. /// </summary> /// <param name="pawn">Pawn to be considered. Used in checking equipment and position when looking for nearby things.</param> /// <param name="curSlot">Pawn's LoadoutSlot being considered.</param> /// <param name="findCount">Amount of Thing of ThingDef to try and pickup.</param> /// <param name="curPriority">Priority of the job.</param> /// <param name="curThing">Thing found near pawn for potential pickup.</param> /// <param name="curCarrier">Pawn that is holding the curThing that 'pawn' wants.</param> /// <remarks>Was split off into a sepearate method so the code could be run from multiple places in caller but that is no longer needed.</remarks> private void FindPickup(Pawn pawn, LoadoutSlot curSlot, int findCount, out ItemPriority curPriority, out Thing curThing, out Pawn curCarrier) { curPriority = ItemPriority.None; curThing = null; curCarrier = null; Predicate <Thing> isFoodInPrison = (Thing t) => t.GetRoom().isPrisonCell&& t.def.IsNutritionGivingIngestible && pawn.Faction.IsPlayer; // Hint: The following block defines how to find items... pay special attention to the Predicates below. ThingRequest req; if (curSlot.genericDef != null) { req = ThingRequest.ForGroup(ThingRequestGroup.HaulableEver); } else { req = curSlot.thingDef.Minifiable ? ThingRequest.ForGroup(ThingRequestGroup.MinifiedThing) : ThingRequest.ForDef(curSlot.thingDef); } Predicate <Thing> findItem; if (curSlot.genericDef != null) { findItem = t => curSlot.genericDef.lambda(t.GetInnerIfMinified().def); } else { findItem = t => t.GetInnerIfMinified().def == curSlot.thingDef; } Predicate <Thing> search = t => findItem(t) && !t.IsForbidden(pawn) && pawn.CanReserve(t) && !isFoodInPrison(t); // look for a thing near the pawn. curThing = GenClosest.ClosestThingReachable( pawn.Position, pawn.Map, req, PathEndMode.ClosestTouch, TraverseParms.For(pawn, Danger.None, TraverseMode.ByPawn), ProximitySearchRadius, search); if (curThing != null) { curPriority = ItemPriority.Proximity; } else { // look for a thing basically anywhere on the map. curThing = GenClosest.ClosestThingReachable( pawn.Position, pawn.Map, req, PathEndMode.ClosestTouch, TraverseParms.For(pawn, Danger.None, TraverseMode.ByPawn), MaximumSearchRadius, search); if (curThing == null && pawn.Map != null) { // look for a thing inside caravan pack animals and prisoners. EXCLUDE other colonists to avoid looping state. List <Pawn> carriers = pawn.Map.mapPawns.AllPawns.Where( p => p.inventory.innerContainer.Count > 0 && (p.RaceProps.packAnimal && p.Faction == pawn.Faction || p.IsPrisoner && p.HostFaction == pawn.Faction) && pawn.CanReserveAndReach(p, PathEndMode.ClosestTouch, Danger.Deadly, int.MaxValue, 0)).ToList(); foreach (Pawn carrier in carriers) { Thing thing = carrier.inventory.innerContainer.FirstOrDefault(t => findItem(t)); if (thing != null) { curThing = thing; curCarrier = carrier; break; } } } if (curThing != null) { if (!curThing.def.IsNutritionGivingIngestible && findCount / curSlot.count <= 0.5f) { curPriority = ItemPriority.LowStock; } else { curPriority = ItemPriority.Low; } } } }
//public float y=0f; public override IEnumerable <Gizmo> CompGetGizmosExtra() { foreach (var g in base.CompGetGizmosExtra()) { yield return(g); } yield return(new Command_Action { icon = ContentFinder <Texture2D> .Get("UI/Commands/RenameZone"), defaultLabel = "CommandRenameZoneLabel".Translate(), action = delegate { Find.WindowStack.Add(new Dialog_RenameDSU(this)); }, hotKey = KeyBindingDefOf.Misc1 }); #if DEBUG yield return(new Command_Action { defaultLabel = "Items in Region", action = delegate { Log.Warning("ListerThings for " + parent + " (at region at position " + parent.Position + ")"); foreach (var t in parent.Position.GetRegion(parent.Map).ListerThings .ThingsMatching(ThingRequest.ForGroup(ThingRequestGroup.HaulableEver))) { Log.Message(" " + t); } } }); #endif #if false yield return(new Command_Action { defaultLabel = "Y-=.1", action = delegate() { y -= 0.1f; Messages.Message("Offset: " + y, MessageTypeDefOf.NeutralEvent); } }); yield return(new Command_Action { defaultLabel = "Y+=.1", action = delegate() { y += 0.1f; Messages.Message("Offset: " + y, MessageTypeDefOf.NeutralEvent); } }); #endif // I left this lovely testing code in - oops. //yield return new Command_Action //{ // defaultLabel = "Minus One", // action=delegate () // { // foreach (var cl in parent.GetSlotGroup().CellsList) // { // foreach (Thing t in parent.Map.thingGrid.ThingsAt(cl)) // { // if (t.def.category == ThingCategory.Item) // { // if (t.stackCount > 1) // { // Log.Warning("Lowering " + t.ToString()); // t.stackCount--; // } // }// item // }// each thing // }// each cell // },// end action //}; }
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); }
// Token: 0x06003F17 RID: 16151 RVA: 0x001D8758 File Offset: 0x001D6B58 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) { Thing searcherThing = searcher.Thing; Pawn searcherPawn = searcher as Pawn; Verb verb = searcher.CurrentEffectiveVerb; 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); } 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 (XenomorphTargetFinder.HasRangedAttack(searcher)) { XenomorphTargetFinder.tmpTargets.Clear(); XenomorphTargetFinder.tmpTargets.AddRange(searcherThing.Map.attackTargetsCache.GetPotentialTargetsFor(searcher)); if ((byte)(flags & TargetScanFlags.NeedReachable) != 0) { Predicate <IAttackTarget> oldValidator = innerValidator; innerValidator = ((IAttackTarget t) => oldValidator(t) && XenomorphTargetFinder.CanReach(searcherThing, t.Thing, canBash)); } bool flag = false; for (int i = 0; i < XenomorphTargetFinder.tmpTargets.Count; i++) { IAttackTarget attackTarget = XenomorphTargetFinder.tmpTargets[i]; if (attackTarget.Thing.Position.InHorDistOf(searcherThing.Position, maxDist) && innerValidator(attackTarget) && XenomorphTargetFinder.CanShootAtFromCurrentPosition(attackTarget, searcher, verb)) { flag = true; break; } } IAttackTarget result; if (flag) { XenomorphTargetFinder.tmpTargets.RemoveAll((IAttackTarget x) => !x.Thing.Position.InHorDistOf(searcherThing.Position, maxDist) || !innerValidator(x)); result = XenomorphTargetFinder.GetRandomShootingTargetByScore(XenomorphTargetFinder.tmpTargets, searcher, verb); } else { Predicate <Thing> validator2; if ((byte)(flags & TargetScanFlags.NeedReachableIfCantHitFromMyPos) != 0 && (byte)(flags & TargetScanFlags.NeedReachable) == 0) { validator2 = ((Thing t) => innerValidator((IAttackTarget)t) && (XenomorphTargetFinder.CanReach(searcherThing, t, canBash) || XenomorphTargetFinder.CanShootAtFromCurrentPosition((IAttackTarget)t, searcher, verb))); } else { validator2 = ((Thing t) => innerValidator((IAttackTarget)t)); } result = (IAttackTarget)GenClosest.ClosestThing_Global(searcherThing.Position, XenomorphTargetFinder.tmpTargets, maxDist, validator2, null); } XenomorphTargetFinder.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 = XenomorphTargetFinder.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); }
//regular Toils_Haul.CheckForGetOpportunityDuplicate isn't going to work for our purposes, since we're not carrying anything. //Carrying something yields weird results with unspawning errors when transfering to inventory, so we copy-past-- I mean, implement our own. public Toil CheckForOtherItemsToHaulToInventory(Toil getHaulTargetToil, TargetIndex haulableInd, float distanceToOthers, Predicate <Thing> extraValidator = null) { Toil toil = new Toil(); toil.initAction = delegate { Pawn actor = toil.actor; Job curJob = actor.jobs.curJob; IntVec3 storeCell = IntVec3.Invalid; Predicate <Thing> validator = (Thing t) => t.Spawned && HaulAIUtility.PawnCanAutomaticallyHaulFast(actor, t, false) && (!t.IsInValidBestStorage()) && !t.IsForbidden(actor) && !(t is Corpse) && (StoreUtility.TryFindBestBetterStoreCellFor(t, pawn, pawn.Map, (HaulAIUtility.StoragePriorityAtFor(t.Position, t)), actor.Faction, out storeCell, true)) && (extraValidator == null || extraValidator(t)) && actor.CanReserve(t, 1, -1, null, false); Thing thing = GenClosest.ClosestThingReachable(actor.Position, actor.Map, ThingRequest.ForGroup(ThingRequestGroup.HaulableAlways), PathEndMode.ClosestTouch, TraverseParms.For(actor, Danger.Deadly, TraverseMode.ByPawn, false), Math.Max(distanceToOthers, 12f), validator, null, 0, -1, false, RegionType.Set_Passable, false); float usedBulkByPct = 1f; float usedWeightByPct = 1f; try { ((Action)(() => { if (ModCompatibilityCheck.CombatExtendedIsActive) { CombatExtended.CompInventory ceCompInventory = actor.GetComp <CombatExtended.CompInventory>(); usedWeightByPct = ceCompInventory.currentWeight / ceCompInventory.capacityWeight; usedBulkByPct = ceCompInventory.currentBulk / ceCompInventory.capacityBulk; } }))(); } catch (TypeLoadException) { } if (thing != null && (MassUtility.EncumbrancePercent(actor) <= 0.9f || usedBulkByPct >= 0.7f || usedWeightByPct >= 0.8f)) { curJob.SetTarget(haulableInd, thing); actor.Reserve(storeCell, this.job, 1, -1, null); actor.jobs.curDriver.JumpToToil(getHaulTargetToil); return; } if (thing != null) { Job haul = HaulAIUtility.HaulToStorageJob(actor, thing); if (haul?.TryMakePreToilReservations(actor) ?? false) { actor.jobs.jobQueue.EnqueueFirst(haul, new JobTag?(JobTag.Misc)); this.EndJobWith(JobCondition.Succeeded); } } if (thing == null) { Job job = new Job(PickUpAndHaulJobDefOf.UnloadYourHauledInventory); if (job.TryMakePreToilReservations(actor)) { actor.jobs.jobQueue.EnqueueFirst(job, new JobTag?(JobTag.Misc)); this.EndJobWith(JobCondition.Succeeded); } } }; return(toil); }
protected override Job TryGiveJob(Pawn pawn) { if (pawn.Downed) { return(null); } Predicate <Thing> validator = (Thing t) => t.def.category == ThingCategory.Item && t.IngestibleNow && pawn.RaceProps.CanEverEat(t) && pawn.CanReserve(t, 1, -1, null, false); Thing thing = GenClosest.ClosestThingReachable(pawn.Position, pawn.Map, ThingRequest.ForGroup(ThingRequestGroup.HaulableAlways), PathEndMode.OnCell, TraverseParms.For(pawn, Danger.Deadly, TraverseMode.ByPawn, false), 10f, validator, null, 0, -1, false, RegionType.Set_Passable, false); if (thing == null) { return(null); } return(new Job(JobDefOf.Ingest, thing)); }
protected override Job TryGiveJob(Pawn pawn) { if (ShouldSkip(pawn)) { return(null); } Predicate <Thing> predicate = (Thing x) => HasJobOnThing(pawn, x); Thing t = GenClosest.ClosestThingReachable(pawn.Position, pawn.Map, ThingRequest.ForGroup(ThingRequestGroup.Pawn), PathEndMode, TraverseParms.For(pawn, Danger.Some, TraverseMode.ByPawn), 100f, predicate, PotentialWorkThingsGlobal(pawn)); if (t is null) { return(null); } return(JobMaker.MakeJob(JobDefOf.Slaughter, t)); }
protected override Job TryGiveJob(Pawn pawn) { if (pawn.inventory == null) { return(null); } float invNutrition = this.GetInventoryPackableFoodNutrition(pawn); if (invNutrition > 0.4f) { return(null); } if (pawn.Map.resourceCounter.TotalHumanEdibleNutrition < (float)pawn.Map.mapPawns.ColonistsSpawnedCount * 1.5f) { return(null); } Thing thing = GenClosest.ClosestThing_Regionwise_ReachablePrioritized(pawn.Position, pawn.Map, ThingRequest.ForGroup(ThingRequestGroup.FoodSourceNotPlantOrTree), PathEndMode.ClosestTouch, TraverseParms.For(pawn, Danger.Deadly, TraverseMode.ByPawn, false), 20f, delegate(Thing t) { if (!this.IsGoodPackableFoodFor(t, pawn) || t.IsForbidden(pawn) || !pawn.CanReserve(t, 1, -1, null, false) || !t.IsSociallyProper(pawn)) { return(false); } float num3 = invNutrition + t.GetStatValue(StatDefOf.Nutrition, true) * (float)t.stackCount; if (num3 < 0.8f) { return(false); } List <ThoughtDef> list = FoodUtility.ThoughtsFromIngesting(pawn, t, FoodUtility.GetFinalIngestibleDef(t, false)); for (int i = 0; i < list.Count; i++) { if (list[i].stages[0].baseMoodEffect < 0f) { return(false); } } return(true); }, (Thing x) => FoodUtility.FoodOptimality(pawn, x, FoodUtility.GetFinalIngestibleDef(x, false), 0f, false), 24, 30); if (thing == null) { return(null); } float num = pawn.needs.food.MaxLevel - invNutrition; int num2 = Mathf.FloorToInt(num / thing.GetStatValue(StatDefOf.Nutrition, true)); num2 = Mathf.Min(num2, thing.stackCount); num2 = Mathf.Max(num2, 1); return(new Job(JobDefOf.TakeInventory, thing) { count = num2 }); }
public override void CompTickRare() { base.CompTickRare(); Predicate <Thing> predicate = null; if (Props.onlyHumanlike) { predicate = (Thing t) => (t as Pawn)?.RaceProps.Humanlike ?? false; } Thing thing = null; if (Props.triggerOnPawnInRoom) { foreach (Thing containedAndAdjacentThing in parent.GetRoom().ContainedAndAdjacentThings) { if (predicate(containedAndAdjacentThing)) { thing = containedAndAdjacentThing; break; } } } if (thing == null && Props.radius > 0f) { thing = GenClosest.ClosestThingReachable(parent.Position, parent.Map, ThingRequest.ForGroup(ThingRequestGroup.Pawn), PathEndMode.OnCell, TraverseParms.For(TraverseMode.NoPassClosedDoors), Props.radius, predicate); } if (thing != null) { Effecter effecter = new Effecter(EffecterDefOf.ActivatorProximityTriggered); effecter.Trigger(parent, TargetInfo.Invalid); effecter.Cleanup(); Messages.Message("MessageActivatorProximityTriggered".Translate(thing), parent, MessageTypeDefOf.ThreatBig); Find.SignalManager.SendSignal(new Signal(signalTag, parent.Named("SUBJECT"))); SoundDefOf.MechanoidsWakeUp.PlayOneShot(new TargetInfo(parent.Position, parent.Map)); sent = true; } }
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)) { // Log.Messageage(thing + " lord ValidateAttackTarget: false"); return(false); } } if ((flags & TargetScanFlags.NeedNotUnderThickRoof) != 0) { RoofDef roof = thing.Position.GetRoof(thing.Map); if (roof != null && roof.isThickRoof) { // Log.Messageage(thing + " isThickRoof: false"); return(false); } } if ((flags & TargetScanFlags.NeedLOSToAll) != 0) { if (losValidator != null && (!losValidator(searcherThing.Position) || !losValidator(thing.Position))) { // Log.Messageage(thing + " LOSToAll: false"); return(false); } if (!searcherThing.CanSee(thing, losValidator)) { if (t is Pawn) { if ((flags & TargetScanFlags.NeedLOSToPawns) != 0) { // Log.Messageage(thing + " LOSToPawns: false"); return(false); } } else if ((flags & TargetScanFlags.NeedLOSToNonPawns) != 0) { // Log.Messageage(thing + " LOSToNonPawns: false"); return(false); } } } if (((flags & TargetScanFlags.NeedThreat) != 0 || (flags & TargetScanFlags.NeedAutoTargetable) != 0) && t.ThreatDisabled(searcher)) { // Log.Messageage(thing + " NeedThreat: false"); return(false); } if ((flags & TargetScanFlags.NeedAutoTargetable) != 0 && !IsAutoTargetable(t)) { // Log.Messageage(thing + " NeedAutoTargetable: false"); return(false); } if ((flags & TargetScanFlags.NeedActiveThreat) != 0 && !GenHostility.IsActiveThreatTo(t, searcher.Thing.Faction)) { // Log.Messageage(thing + " NeedActiveThreat: false"); return(false); } Pawn pawn = t as Pawn; if (onlyTargetMachines && pawn != null && pawn.RaceProps.IsFlesh) { // Log.Messageage(thing + " onlyTargetMachines: false"); return(false); } if ((flags & TargetScanFlags.NeedNonBurning) != 0 && thing.IsBurning()) { // Log.Messageage(thing + " NeedNonBurning: false"); return(false); } if (searcherThing.def.race != null && (int)searcherThing.def.race.intelligence >= 2) { CompExplosive compExplosive = thing.TryGetComp <CompExplosive>(); if (compExplosive != null && compExplosive.wickStarted) { // Log.Messageage(thing + " wickStarted: false"); return(false); } } if (thing.def.size.x == 1 && thing.def.size.z == 1) { if (thing.Position.Fogged(thing.Map)) { // Log.Messageage(thing + " Fogged: false"); return(false); } } else { bool flag2 = false; foreach (IntVec3 item in thing.OccupiedRect()) { if (!item.Fogged(thing.Map)) { flag2 = true; break; } } if (!flag2) { // Log.Messageage(thing + " Fogged: false"); return(false); } } // Log.Messageage(thing + " valid: true"); return(true); }; if (HasRangedAttack(searcher) && (searcherPawn == null || !searcherPawn.InAggroMentalState)) { // Log.Messageage(searcher + "AttackTargetFinder.HasRangedAttack 0"); tmpTargets.Clear(); // Log.Messageage(searcher + "AttackTargetFinder.HasRangedAttack 1"); tmpTargets.AddRange(searcherThing.Map.attackTargetsCache.GetPotentialTargetsFor(searcher)); // Log.Messageage(searcher + "AttackTargetFinder.HasRangedAttack 2 tmpTargets: " + tmpTargets.Count); if ((flags & TargetScanFlags.NeedReachable) != 0) { Predicate <IAttackTarget> oldValidator2 = innerValidator; innerValidator = ((IAttackTarget t) => oldValidator2(t) && CanReach(searcherThing, t.Thing, canBash)); } // Log.Messageage(searcher + "AttackTargetFinder.HasRangedAttack 3"); 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; } } // Log.Messageage(searcher + "AttackTargetFinder.HasRangedAttack 4 "); IAttackTarget attackTarget2; if (flag) { tmpTargets.RemoveAll((IAttackTarget x) => !x.Thing.Position.InHorDistOf(searcherThing.Position, maxDist) || !innerValidator(x)); attackTarget2 = GetRandomShootingTargetByScore(tmpTargets, searcher, verb); } else { attackTarget2 = (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); } // Log.Messageage(searcher + "AttackTargetFinder.HasRangedAttack 5"); tmpTargets.Clear(); // Log.Messageage(searcher + "AttackTargetFinder.HasRangedAttack tgt found: " + (attackTarget2 != null).ToString()); return(attackTarget2); } // Log.Messageage(searcher + "AttackTargetFinder.HasRangedAttack no ranged attack found"); 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)); } IAttackTarget attackTarget3 = (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 (attackTarget3 != null && PawnUtility.ShouldCollideWithPawns(searcherPawn)) { IAttackTarget attackTarget4 = FindBestReachableMeleeTarget(innerValidator, searcherPawn, maxDist, canBash); if (attackTarget4 != null) { float lengthHorizontal = (searcherPawn.Position - attackTarget3.Thing.Position).LengthHorizontal; float lengthHorizontal2 = (searcherPawn.Position - attackTarget4.Thing.Position).LengthHorizontal; if (Mathf.Abs(lengthHorizontal - lengthHorizontal2) < 50f) { attackTarget3 = attackTarget4; } } } return(attackTarget3); }