public static Building_HackingTable GetAvailableHackingTable(Pawn pawn, Pawn targetPawn) { return((Building_HackingTable)GenClosest.ClosestThingReachable(targetPawn.Position, targetPawn.Map, ThingRequest.ForDef(WTH_DefOf.WTH_HackingTable), PathEndMode.OnCell, TraverseParms.For(pawn, Danger.Deadly, TraverseMode.ByPawn, false), 9999f, delegate(Thing b) { if (b is Building_HackingTable ht && ht.TryGetComp <CompFlickable>() is CompFlickable flickable && flickable.SwitchIsOn && !b.IsBurning() && !b.IsForbidden(pawn) && pawn.CanReserve(b)) { if (!(ht.GetCurOccupant(Building_HackingTable.SLOTINDEX) is Pawn pawnOnTable && pawnOnTable.OnHackingTable())) { return true; } } return false; })); }
public override void PostRemoved() { base.PostRemoved(); float chance = 0.5f + ((float)ExtraTargets / 10) - ((float)TimesBounced / 10); // Log.Message(string.Format("chance: {0} = 0.5f + ({1} / 10) - ({2} / 10)", chance, ExtraTargets, TimesBounced)); bool shouldBounce = Rand.Chance(chance) && TimesBounced < ExtraTargets; // Log.Message(string.Format("shouldBounce: {0} 1", shouldBounce)); IntVec3 hitpos = !this.pawn.Dead ? this.pawn.Position : this.pawn.PositionHeld; Map hitmap = !this.pawn.Dead ? this.pawn.Map : this.pawn.MapHeld; Thing launcher = this.pawn; // Log.Message(string.Format("shouldBounce: {0} 2", shouldBounce)); Projectile projectile = shouldBounce ? this.OriginalProjectile : (Projectile)ThingMaker.MakeThing(ReturnDef, null); // Log.Message(string.Format("projectile: {0} 3", projectile)); // Thing launcher = this.OriginalWeapon != null ? this.OriginalWeapon : null; // Thing launcher = this.OriginalWeapon != null ? this.OriginalWeapon : null; string msg = shouldBounce ? "bouncing" : "returning"; // Log.Message(string.Format("shouldBounce: {0} 4", msg)); Thing targetthing; // Log.Message(string.Format("finding ")); if (shouldBounce) { // Log.Message(string.Format("hostile target")); targetthing = GenClosest.ClosestThingReachable(hitpos, hitmap, ThingRequest.ForGroup(ThingRequestGroup.Pawn), Verse.AI.PathEndMode.Touch, TraverseParms.For(TraverseMode.NoPassClosedDoors, Danger.Deadly, false), 10f, x => (x.Faction.HostileTo(this.OriginalPawn.Faction)) && x != this.pawn, null, 0, -1, false, RegionType.Set_Passable, false); if (targetthing == null) { if (!this.pawn.Dead) { targetthing = this.pawn; } else { targetthing = (Thing)this.OriginalPawn; } } } else { // Log.Message(string.Format("Original pawn")); targetthing = (Thing)this.OriginalPawn; // Log.Message(string.Format("{0}", this.OriginalPawn.LabelShortCap)); } if (shouldBounce) { TimesBounced++; } // Log.Message(string.Format("TimesBounced: {0}", TimesBounced)); if (shouldBounce) { Returning_Projectile Rprojectile = (Returning_Projectile)projectile; // Log.Message(string.Format("converting and storing ")); Rprojectile.timesBounced = this.TimesBounced; Rprojectile.OriginalPawn = this.OriginalPawn; Rprojectile.OriginalWeapon = this.OriginalWeapon; Rprojectile.OriginalProjectile = this.OriginalProjectile; // Log.Message(string.Format("TimesBounced: {0}, OriginalPawn: {1}, OriginalWeapon: {2}, OriginalProjectile: {3}, ", this.TimesBounced, this.OriginalPawn, this.OriginalWeapon, this.OriginalProjectile)); GenSpawn.Spawn(Rprojectile, hitpos, hitmap, 0); // Log.Message(string.Format("GenSpawn")); Rprojectile.Launch(this.pawn, hitpos.ToVector3(), targetthing, targetthing, ProjectileHitFlags.IntendedTarget, OriginalPawn.equipment.Primary); // Log.Message(string.Format("Launch: ") + msg); // Log.Message(msg); } else { GenSpawn.Spawn(projectile, hitpos, hitmap, 0); // Log.Message(string.Format("GenSpawn")); projectile.Launch(this.pawn, hitpos.ToVector3(), targetthing, targetthing, ProjectileHitFlags.IntendedTarget, launcher); // Log.Message(string.Format("Launch: ") + msg); // Log.Message(msg); } }
protected override Job TryGiveJob(Pawn pawn) { Room room = pawn.GetRoom(RegionType.Set_Passable); if (room != null) { if (room.PsychologicallyOutdoors) { Area area = pawn.MapHeld.areaManager.Home; if (area != null) { if (area.ActiveCells.FirstOrDefault(x => x.Roofed(pawn.Map) && x.Walkable(pawn.Map)) is IntVec3 safePlace && !IsZero(safePlace) && safePlace.IsValid) { //Log.Message("Safe Place"); return(new Job(JobDefOf.Goto, safePlace) { locomotionUrgency = LocomotionUrgency.Sprint }); } } Thing thing = GenClosest.ClosestThingReachable(pawn.PositionHeld, pawn.Map, ThingRequest.ForDef(ThingDefOf.Fire), PathEndMode.Touch, TraverseParms.For(pawn, Danger.Deadly, TraverseMode.ByPawn, false), 23, null, null, 0, -1, false, RegionType.Set_Passable, false); if (thing != null) { //Log.Message("Flee Place"); IntVec3 fleeLoc = CellFinderLoose.GetFleeDest(pawn, new List <Thing>() { thing }, 23); return(new Job(JobDefOf.FleeAndCower, thing)); } Region region; CellFinder.TryFindClosestRegionWith(pawn.GetRegion(RegionType.Set_Passable), TraverseParms.For(pawn, Danger.Deadly, TraverseMode.ByPawn), (x => !x.Room.PsychologicallyOutdoors), 9999, out region, RegionType.Set_All); //.ClosestRegionIndoors(pawn.Position, pawn.Map, TraverseParms.For(pawn, Danger.Deadly, TraverseMode.ByPawn, false), RegionType.Set_Passable); if (region != null) { IntVec3 result; if (region.TryFindRandomCellInRegion(x => !IsZero(x) && x.IsValid && x.InBounds(pawn.MapHeld) && x.GetDoor(pawn.MapHeld) == null, out result)) { //Log.Message("Region Place"); return(new Job(JobDefOf.Goto, result) { locomotionUrgency = LocomotionUrgency.Sprint }); } } IntVec3?cellResult = null; cellResult = CellFinderLoose.RandomCellWith(x => !IsZero(x) && x.IsValid && x.InBounds(pawn.MapHeld) && x.Roofed(pawn.MapHeld) && x.Walkable(pawn.MapHeld) && pawn.Map.reachability.CanReach(pawn.PositionHeld, x, PathEndMode.OnCell, TraverseMode.ByPawn, Danger.Deadly), pawn.MapHeld, 1000); if (cellResult != null && cellResult.Value.IsValid && !IsZero(cellResult.Value)) { //Log.Message("Random Place"); return(new Job(JobDefOf.Goto, cellResult.Value) { locomotionUrgency = LocomotionUrgency.Sprint }); } if (pawn.Faction != pawn.Map.ParentFaction) { bool flag = false; if (pawn.mindState.duty != null && pawn.mindState.duty.canDig) { flag = true; } IntVec3 c; if (RCellFinder.TryFindBestExitSpot(pawn, out c, (!flag) ? TraverseMode.ByPawn : TraverseMode.PassAllDestroyableThings)) { if (flag) { using (PawnPath pawnPath = pawn.Map.pathFinder.FindPath(pawn.Position, c, TraverseParms.For(pawn, Danger.Deadly, TraverseMode.PassAllDestroyableThings, false), PathEndMode.OnCell)) { IntVec3 cellBeforeBlocker; Thing thingY = pawnPath.FirstBlockingBuilding(out cellBeforeBlocker, pawn); if (thingY != null) { Job job = DigUtility.PassBlockerJob(pawn, thingY, cellBeforeBlocker, true); if (job != null) { return(job); } } } } return(new Job(JobDefOf.Goto, c) { exitMapOnArrival = true, locomotionUrgency = PawnUtility.ResolveLocomotion(pawn, LocomotionUrgency.Sprint, LocomotionUrgency.Jog), expiryInterval = 400, canBash = true }); } } IntVec3?hideyHoleResult = null; hideyHoleResult = VampireUtility.FindHideyHoleSpot(VampDefOf.ROMV_HideyHole, Rot4.Random, pawn.PositionHeld, pawn.MapHeld); if (hideyHoleResult != null && hideyHoleResult.Value.IsValid) { //Log.Message("Hidey Place"); return(new Job(VampDefOf.ROMV_DigAndHide, hideyHoleResult.Value) { locomotionUrgency = LocomotionUrgency.Sprint }); } } //bool nextMoveOrderIsWait = pawn.mindState.nextMoveOrderIsWait; //pawn.mindState.nextMoveOrderIsWait = !pawn.mindState.nextMoveOrderIsWait; //if (nextMoveOrderIsWait) //{ // return new Job(JobDefOf.WaitWander) // { // expiryInterval = this.ticksBetweenWandersRange.RandomInRange // }; //} //IntVec3 exactWanderDest = this.GetExactWanderDest(pawn); //if (!exactWanderDest.IsValid) //{ // pawn.mindState.nextMoveOrderIsWait = false; // return null; //} //pawn.Map.pawnDestinationManager.ReserveDestinationFor(pawn, exactWanderDest); //return new Job(JobDefOf.GotoWander, exactWanderDest) //{ // locomotionUrgency = this.locomotionUrgency //}; } return(null); }
// Token: 0x060032A0 RID: 12960 RVA: 0x001196A0 File Offset: 0x001178A0 private Hive FindClosestHive(Pawn pawn) { ThingDef hiveDef = RimWorld.ThingDefOf.Hive; Hive hive = null; bool pawnFaction = pawn.Faction != null; bool pawnDefaultFaction = pawn.kindDef.defaultFactionType != null; FactionDef factionDef = pawnFaction ? pawn.Faction.def : (pawnDefaultFaction ? pawn.kindDef.defaultFactionType : null); if (factionDef == null) { return(null); } List <ThingDef> defs = factionDef.HivedefsFor(); if (pawn.Faction != null && !defs.NullOrEmpty()) { foreach (ThingDef td in defs) { hiveDef = td; hive = GenClosest.ClosestThingReachable(pawn.Position, pawn.Map, ThingRequest.ForDef(hiveDef), PathEndMode.Touch, TraverseParms.For(pawn, Danger.Deadly, TraverseMode.ByPawn, false), 30f, (Thing x) => x.Faction == pawn.Faction, null, 0, 30, false, RegionType.Set_Passable, false) as Hive; if (hive != null) { return(hive); } } } return(GenClosest.ClosestThingReachable(pawn.Position, pawn.Map, ThingRequest.ForDef(hiveDef), PathEndMode.Touch, TraverseParms.For(pawn, Danger.Deadly, TraverseMode.ByPawn, false), 30f, (Thing x) => x.Faction == pawn.Faction, null, 0, 30, false, RegionType.Set_Passable, false) as Hive); }
private static Thing FindThingToLoad(Pawn p, ShipBase ship) { LoadShipCargoUtility.neededThings.Clear(); List <TransferableOneWay> leftToLoad = ship.compShip.leftToLoad; if (leftToLoad != null) { for (int i = 0; i < leftToLoad.Count; i++) { TransferableOneWay transferableOneWay = leftToLoad[i]; if (transferableOneWay.countToTransfer > 0) { for (int j = 0; j < transferableOneWay.things.Count; j++) { LoadShipCargoUtility.neededThings.Add(transferableOneWay.things[j]); // Log.Message(transferableOneWay.things[j].Label); } } } } if (!LoadShipCargoUtility.neededThings.Any <Thing>()) { return(null); } Predicate <Thing> validator = (Thing x) => LoadShipCargoUtility.neededThings.Contains(x) && p.CanReserve(x, 1); Thing thing = GenClosest.ClosestThingReachable(p.Position, p.Map, ThingRequest.ForGroup(ThingRequestGroup.HaulableEver), PathEndMode.Touch, TraverseParms.For(p, Danger.Deadly, TraverseMode.ByPawn, false), 9999f, validator, null, -1, false); if (thing == null) { foreach (Thing current in LoadShipCargoUtility.neededThings) { Pawn pawn = current as Pawn; if (pawn != null && (!pawn.IsColonist || pawn.Downed) && p.CanReserveAndReach(pawn, PathEndMode.Touch, Danger.Deadly, 1)) { return(pawn); } } } LoadShipCargoUtility.neededThings.Clear(); return(thing); }
public static Building_MutagenChamber FindCryptosleepCasketFor(Pawn p, Pawn traveler, bool ignoreOtherReservations = false) { IEnumerable <ThingDef> enumerable = from def in DefDatabase <ThingDef> .AllDefs where typeof(Building_MutagenChamber).IsAssignableFrom(def.thingClass) select def; foreach (ThingDef item in enumerable) { Building_MutagenChamber building_MutagenChamber = (Building_MutagenChamber)GenClosest.ClosestThingReachable(p.Position, p.Map, ThingRequest.ForDef(item), PathEndMode.InteractionCell, TraverseParms.For(traveler), 9999f, delegate(Thing x) { int result; if (!((Building_MutagenChamber)x).HasAnyContents && ((Building_MutagenChamber)x).flickComp.SwitchIsOn) { Pawn p2 = traveler; LocalTargetInfo target = x; bool ignoreOtherReservations2 = ignoreOtherReservations; result = (p2.CanReserve(target, 1, -1, null, ignoreOtherReservations2) ? 1 : 0); } else { result = 0; } return((byte)result != 0); }); if (building_MutagenChamber != null) { return(building_MutagenChamber); } } return(null); }
public static Corpse GetClosestCorpseToDigUp(Pawn pawn) { if (!pawn.Spawned) { return(null); } Building_Grave building_Grave = (Building_Grave)GenClosest.ClosestThingReachable(pawn.Position, pawn.Map, ThingRequest.ForGroup(ThingRequestGroup.Grave), PathEndMode.InteractionCell, TraverseParms.For(pawn, Danger.Deadly, TraverseMode.ByPawn, false), 9999f, delegate(Thing x) { Building_Grave building_Grave2 = (Building_Grave)x; return(building_Grave2.HasCorpse && IsChosenCorpseValid(building_Grave2.Corpse, pawn, true)); }, null, 0, -1, false, RegionType.Set_Passable, false); return(building_Grave?.Corpse); }
// Token: 0x06003EF3 RID: 16115 RVA: 0x001D7E89 File Offset: 0x001D6289 protected override IntVec3 GetWanderRoot(Pawn pawn) { bool anyPotentialHosts = !pawn.Map.ViableHosts().NullOrEmpty(); if (anyPotentialHosts) { bool anyReachablePotentialHosts = pawn.Map.ViableHosts().Any(x => pawn.CanReach(x, PathEndMode.ClosestTouch, Danger.Deadly, false, TraverseMode.NoPassClosedDoors)); if (anyReachablePotentialHosts) { Pawn potentialHost = (Pawn)GenClosest.ClosestThingReachable(pawn.Position, pawn.Map, ThingRequest.ForGroup(ThingRequestGroup.Pawn), PathEndMode.ClosestTouch, TraverseParms.For(TraverseMode.NoPassClosedDoors, Danger.Some), float.MaxValue, (x => ((Pawn)x).isPotentialHost())) ?? null; if (potentialHost != null) { Predicate <IntVec3> validator = delegate(IntVec3 y) { return(XenomorphUtil.DistanceBetween(y, potentialHost.Position) < XenomorphUtil.DistanceBetween(y, pawn.Position)); }; if (RCellFinder.TryFindRandomCellNearWith(pawn.Position, validator, pawn.Map, out IntVec3 lc, 6, (int)wanderRadius)) { return(lc); } } } } return(pawn.Position); }
public static bool TryFindGoodKidnapVictim(Pawn kidnapper, float maxDist, out Pawn victim, List <Thing> disallowed = null) { if (!kidnapper.health.capacities.CapableOf(PawnCapacityDefOf.Manipulation) || !kidnapper.Map.reachability.CanReachMapEdge(kidnapper.Position, TraverseParms.For(kidnapper, Danger.Some, TraverseMode.ByPawn, false))) { victim = null; return(false); } Predicate <Thing> validator = delegate(Thing t) { Pawn pawn = t as Pawn; return(pawn.RaceProps.Humanlike && pawn.Downed && pawn.Faction == Faction.OfPlayer && pawn.Faction.HostileTo(kidnapper.Faction) && kidnapper.CanReserve(pawn, 1, -1, null, false) && (disallowed == null || !disallowed.Contains(pawn))); }; victim = (Pawn)GenClosest.ClosestThingReachable(kidnapper.Position, kidnapper.Map, ThingRequest.ForGroup(ThingRequestGroup.Pawn), PathEndMode.OnCell, TraverseParms.For(TraverseMode.NoPassClosedDoors, Danger.Some, false), maxDist, validator, null, 0, -1, false, RegionType.Set_Passable, false); return(victim != null); }
public static Building_CashRegister GetClosestRegister([NotNull] this Pawn pawn) { return((Building_CashRegister)GenClosest.ClosestThingReachable(pawn.Position, pawn.Map, ThingRequest.ForDef(cashRegisterDef), PathEndMode.Touch, TraverseParms.For(pawn), 90f, x => x.Faction == pawn.Faction, null, 0, 30)); }
public override Job TryGiveJob(Pawn pawn) { Pawn targetPawn = GenClosest.ClosestThingReachable(pawn.Position, pawn.Map, ThingRequest.ForGroup(ThingRequestGroup.Pawn), PathEndMode.Touch, TraverseParms.For(pawn, Danger.None, TraverseMode.ByPawn, false), maxDistance: this.def.searchDistance, validator: (Thing x) => { Pawn p = x as Pawn; if (p.CurJob == null || p.CurJobDef.driverClass != this.def.targetJobDriver) { return(false); } return(true); }) as Pawn; if (targetPawn != null) { return(new Job(this.def.jobDef, targetPawn) { locomotionUrgency = modSettings.wanderMovePolicy }); } return(null); }
public override ThinkResult TryIssueJobPackage(Pawn pawn, JobIssueParams jobParams) { //List<WorkGiver> list = this.emergency ? pawn.workSettings.WorkGiversInOrderEmergency : pawn.workSettings.WorkGiversInOrderNormal; int num = -999; TargetInfo targetInfo = TargetInfo.Invalid; WorkGiver_Scanner workGiver_Scanner = null; WorkGiver workGiver = DefDatabase <WorkGiverDef> .GetNamed("GrowerHarvest", true).Worker; if (workGiver.def.priorityInType != num && targetInfo.IsValid) { // break; } else { if (this.PawnCanUseWorkGiver(pawn, workGiver)) { try { Job job2 = workGiver.NonScanJob(pawn); if (job2 != null) { return(new ThinkResult(job2, this, new JobTag?(workGiver.def.tagToGive), false)); } WorkGiver_Scanner scanner = workGiver as WorkGiver_Scanner; if (scanner != null) { if (scanner.def.scanThings) { Predicate <Thing> predicate = (Thing t) => !t.IsForbidden(pawn) && scanner.HasJobOnThing(pawn, t, false); IEnumerable <Thing> enumerable = scanner.PotentialWorkThingsGlobal(pawn); Thing thing; if (scanner.Prioritized) { IEnumerable <Thing> enumerable2 = enumerable; if (enumerable2 == null) { enumerable2 = pawn.Map.listerThings.ThingsMatching(scanner.PotentialWorkThingRequest); } if (scanner.AllowUnreachable) { IntVec3 position = pawn.Position; IEnumerable <Thing> searchSet = enumerable2; Predicate <Thing> validator = predicate; thing = GenClosest.ClosestThing_Global(position, searchSet, 99999f, validator, (Thing x) => scanner.GetPriority(pawn, x)); } else { IntVec3 position = pawn.Position; Map map = pawn.Map; IEnumerable <Thing> searchSet = enumerable2; PathEndMode pathEndMode = scanner.PathEndMode; TraverseParms traverseParams = TraverseParms.For(pawn, scanner.MaxPathDanger(pawn), TraverseMode.ByPawn, false); Predicate <Thing> validator = predicate; thing = GenClosest.ClosestThing_Global_Reachable(position, map, searchSet, pathEndMode, traverseParams, 9999f, validator, (Thing x) => scanner.GetPriority(pawn, x)); } } else if (scanner.AllowUnreachable) { IEnumerable <Thing> enumerable3 = enumerable; if (enumerable3 == null) { enumerable3 = pawn.Map.listerThings.ThingsMatching(scanner.PotentialWorkThingRequest); } IntVec3 position = pawn.Position; IEnumerable <Thing> searchSet = enumerable3; Predicate <Thing> validator = predicate; thing = GenClosest.ClosestThing_Global(position, searchSet, 99999f, validator, null); } else { IntVec3 position = pawn.Position; Map map = pawn.Map; ThingRequest potentialWorkThingRequest = scanner.PotentialWorkThingRequest; PathEndMode pathEndMode = scanner.PathEndMode; TraverseParms traverseParams = TraverseParms.For(pawn, scanner.MaxPathDanger(pawn), TraverseMode.ByPawn, false); Predicate <Thing> validator = predicate; bool forceGlobalSearch = enumerable != null; thing = GenClosest.ClosestThingReachable(position, map, potentialWorkThingRequest, pathEndMode, traverseParams, 9999f, validator, enumerable, 0, scanner.MaxRegionsToScanBeforeGlobalSearch, forceGlobalSearch, RegionType.Set_Passable, false); } if (thing != null) { targetInfo = thing; workGiver_Scanner = scanner; } } if (scanner.def.scanCells) { IntVec3 position2 = pawn.Position; float num2 = 99999f; float num3 = -3.40282347E+38f; bool prioritized = scanner.Prioritized; bool allowUnreachable = scanner.AllowUnreachable; Danger maxDanger = scanner.MaxPathDanger(pawn); foreach (IntVec3 current in scanner.PotentialWorkCellsGlobal(pawn)) { bool flag = false; float num4 = (float)(current - position2).LengthHorizontalSquared; float num5 = 0f; if (prioritized) { if (!current.IsForbidden(pawn) && scanner.HasJobOnCell(pawn, current, false)) { if (!allowUnreachable && !pawn.CanReach(current, scanner.PathEndMode, maxDanger, false, TraverseMode.ByPawn)) { continue; } num5 = scanner.GetPriority(pawn, current); if (num5 > num3 || (num5 == num3 && num4 < num2)) { flag = true; } } } else if (num4 < num2 && !current.IsForbidden(pawn) && scanner.HasJobOnCell(pawn, current, false)) { if (!allowUnreachable && !pawn.CanReach(current, scanner.PathEndMode, maxDanger, false, TraverseMode.ByPawn)) { continue; } flag = true; } if (flag) { targetInfo = new TargetInfo(current, pawn.Map, false); workGiver_Scanner = scanner; num2 = num4; num3 = num5; } } } } } catch (Exception ex) { Log.Error(string.Concat(new object[] { pawn, " threw exception in WorkGiver ", workGiver.def.defName, ": ", ex.ToString() }), false); } finally { } if (targetInfo.IsValid) { //pawn.mindState.lastGivenWorkType = workGiver.def.workType; Job job3; if (targetInfo.HasThing) { job3 = workGiver_Scanner.JobOnThing(pawn, targetInfo.Thing, false); } else { job3 = workGiver_Scanner.JobOnCell(pawn, targetInfo.Cell, false); } if (job3 != null) { return(new ThinkResult(job3, this, new JobTag?(workGiver.def.tagToGive), false)); } Log.ErrorOnce(string.Concat(new object[] { workGiver_Scanner, " provided target ", targetInfo, " but yielded no actual job for pawn ", pawn, ". The CanGiveJob and JobOnX methods may not be synchronized." }), 6112651, false); } num = workGiver.def.priorityInType; } } return(ThinkResult.NoJob); }
protected override Job TryGiveJob(Pawn pawn) { if (ShouldSkip(pawn)) { return(null); } Predicate <Thing> predicate = (Thing x) => pawn.Map.mapPawns.SlavesAndPrisonersOfColonySpawned.Contains(x); Thing t = GenClosest.ClosestThingReachable(pawn.Position, pawn.Map, ThingRequest.ForGroup(ThingRequestGroup.Pawn), PathEndMode, TraverseParms.For(pawn, Danger.Deadly, TraverseMode.ByPawn), 100f, predicate, PotentialWorkThingsGlobal(pawn)); if (t is null) { return(null); } if (!ShouldTakeCareOfPrisoner(pawn, t)) { return(null); } Pawn pawn2 = (Pawn)t; PrisonerInteractionModeDef interactionMode = pawn2.guest.interactionMode; if ((interactionMode == PrisonerInteractionModeDefOf.AttemptRecruit || interactionMode == PrisonerInteractionModeDefOf.ReduceResistance) && pawn2.guest.ScheduledForInteraction && pawn.health.capacities.CapableOf(PawnCapacityDefOf.Talking) && (!pawn2.Downed || pawn2.InBed()) && pawn.CanReserve(t) && pawn2.Awake()) { if (interactionMode == PrisonerInteractionModeDefOf.ReduceResistance && pawn2.guest.Resistance <= 0f) { return(null); } return(JobMaker.MakeJob(InternalDefOf.GR_HumanoidHybridRecruit, t)); } return(null); }
public override Job TryGiveJob(Pawn pawn) { if (!Controller.settings.EnableAmmoSystem || !Controller.settings.AutoTakeAmmo) { return(null); } if (pawn.Faction == null) //Wild man (b19 incident added) Faction is null { return(null); } if (!pawn.RaceProps.Humanlike || (pawn.story != null && pawn.WorkTagIsDisabled(WorkTags.Violent))) { return(null); } if (pawn.Faction.IsPlayer && pawn.Drafted) { return(null); } if (!Rand.MTBEventOccurs(60, 5, 30)) { return(null); } if (!pawn.Faction.IsPlayer && FindBattleWorthyEnemyPawnsCount(pawn.Map, pawn) > 25) { return(null); } if (pawn.IsPrisoner && (pawn.HostFaction != Faction.OfPlayer || pawn.guest.interactionMode == PrisonerInteractionModeDefOf.Release)) { return(null); } //Log.Message(pawn.ThingID + " - priority:" + (GetPriorityWork(pawn)).ToString() + " capacityWeight: " + pawn.TryGetComp<CompInventory>().capacityWeight.ToString() + " currentWeight: " + pawn.TryGetComp<CompInventory>().currentWeight.ToString() + " capacityBulk: " + pawn.TryGetComp<CompInventory>().capacityBulk.ToString() + " currentBulk: " + pawn.TryGetComp<CompInventory>().currentBulk.ToString()); var brawler = (pawn.story != null && pawn.story.traits != null && pawn.story.traits.HasTrait(TraitDefOf.Brawler)); CompInventory inventory = pawn.TryGetComp <CompInventory>(); bool hasPrimary = (pawn.equipment != null && pawn.equipment.Primary != null); CompAmmoUser primaryAmmoUser = hasPrimary ? pawn.equipment.Primary.TryGetComp <CompAmmoUser>() : null; CompAmmoUser primaryAmmoUserWithInventoryCheck = hasPrimary ? pawn.equipment.Primary.TryGetComp <CompAmmoUser>() : hasWeaponInInventory(pawn) ? weaponInInventory(pawn) : null; if (inventory != null) { // Prefer ranged weapon in inventory if (!pawn.Faction.IsPlayer && hasPrimary && pawn.equipment.Primary.def.IsMeleeWeapon && !brawler) { if ((pawn.skills.GetSkill(SkillDefOf.Shooting).Level >= pawn.skills.GetSkill(SkillDefOf.Melee).Level || pawn.skills.GetSkill(SkillDefOf.Shooting).Level >= 6)) { ThingWithComps InvListGun3 = inventory.rangedWeaponList.Find(thing => thing.TryGetComp <CompAmmoUser>() != null && thing.TryGetComp <CompAmmoUser>().HasAmmoOrMagazine); if (InvListGun3 != null) { inventory.TrySwitchToWeapon(InvListGun3); } } } // Equip weapon if no any weapon if (!pawn.Faction.IsPlayer && !hasPrimary) { // For ranged weapon if ((pawn.skills.GetSkill(SkillDefOf.Shooting).Level >= pawn.skills.GetSkill(SkillDefOf.Melee).Level || pawn.skills.GetSkill(SkillDefOf.Shooting).Level >= 6) && !brawler) { ThingWithComps InvListGun3 = inventory.rangedWeaponList.Find(thing => thing.TryGetComp <CompAmmoUser>() != null && thing.TryGetComp <CompAmmoUser>().HasAmmoOrMagazine); if (InvListGun3 != null) { inventory.TrySwitchToWeapon(InvListGun3); } } else { // For melee weapon ThingWithComps InvListMeleeWeapon = inventory.meleeWeaponList.Find(thing => thing.def.IsMeleeWeapon); if (InvListMeleeWeapon != null) { inventory.TrySwitchToWeapon(InvListMeleeWeapon); } } } var priority = GetPriorityWork(pawn); // Drop excess ranged weapon if (!pawn.Faction.IsPlayer && primaryAmmoUser != null && priority == WorkPriority.Unloading && inventory.rangedWeaponList.Count >= 1) { Thing ListGun = inventory.rangedWeaponList.Find(thing => thing.TryGetComp <CompAmmoUser>() != null && thing.def != pawn.equipment.Primary.def); if (ListGun != null) { Thing ammoListGun = null; if (!ListGun.TryGetComp <CompAmmoUser>().HasAmmoOrMagazine) { foreach (AmmoLink link in ListGun.TryGetComp <CompAmmoUser>().Props.ammoSet.ammoTypes) { if (inventory.ammoList.Find(thing => thing.def == link.ammo) == null) { ammoListGun = ListGun; break; } } } if (ammoListGun != null) { Thing droppedWeapon; if (inventory.container.TryDrop(ListGun, pawn.Position, pawn.Map, ThingPlaceMode.Near, ListGun.stackCount, out droppedWeapon)) { pawn.jobs.EndCurrentJob(JobCondition.None, true); pawn.jobs.TryTakeOrderedJob(JobMaker.MakeJob(JobDefOf.DropEquipment, droppedWeapon, 30, true)); } } } } // Find and drop not need ammo from inventory if (!pawn.Faction.IsPlayer && hasPrimary && inventory.ammoList.Count > 1 && priority == WorkPriority.Unloading) { Thing WrongammoThing = null; WrongammoThing = primaryAmmoUser != null ? inventory.ammoList.Find(thing => !primaryAmmoUser.Props.ammoSet.ammoTypes.Any(a => a.ammo == thing.def)) : inventory.ammoList.RandomElement <Thing>(); if (WrongammoThing != null) { Thing InvListGun = inventory.rangedWeaponList.Find(thing => hasPrimary && thing.TryGetComp <CompAmmoUser>() != null && thing.def != pawn.equipment.Primary.def); if (InvListGun != null) { Thing ammoInvListGun = null; foreach (AmmoLink link in InvListGun.TryGetComp <CompAmmoUser>().Props.ammoSet.ammoTypes) { ammoInvListGun = inventory.ammoList.Find(thing => thing.def == link.ammo); break; } if (ammoInvListGun != null && ammoInvListGun != WrongammoThing) { Thing droppedThingAmmo; if (inventory.container.TryDrop(ammoInvListGun, pawn.Position, pawn.Map, ThingPlaceMode.Near, ammoInvListGun.stackCount, out droppedThingAmmo)) { pawn.jobs.EndCurrentJob(JobCondition.None, true); pawn.jobs.TryTakeOrderedJob(JobMaker.MakeJob(JobDefOf.DropEquipment, 30, true)); } } } else { Thing droppedThing; if (inventory.container.TryDrop(WrongammoThing, pawn.Position, pawn.Map, ThingPlaceMode.Near, WrongammoThing.stackCount, out droppedThing)) { pawn.jobs.EndCurrentJob(JobCondition.None, true); pawn.jobs.TryTakeOrderedJob(JobMaker.MakeJob(JobDefOf.DropEquipment, 30, true)); } } } } // Find weapon in inventory and try to switch if any ammo in inventory. if (priority == WorkPriority.Weapon && !hasPrimary) { ThingWithComps InvListGun2 = inventory.rangedWeaponList.Find(thing => thing.TryGetComp <CompAmmoUser>() != null); if (InvListGun2 != null) { Thing ammoInvListGun2 = null; foreach (AmmoLink link in InvListGun2.TryGetComp <CompAmmoUser>().Props.ammoSet.ammoTypes) { ammoInvListGun2 = inventory.ammoList.Find(thing => thing.def == link.ammo); break; } if (ammoInvListGun2 != null) { inventory.TrySwitchToWeapon(InvListGun2); } } // Find weapon with near ammo for ai. if (!pawn.Faction.IsPlayer) { Predicate <Thing> validatorWS = (Thing w) => w.def.IsWeapon && w.MarketValue > 500 && pawn.CanReserve(w, 1) && pawn.Position.InHorDistOf(w.Position, 25f) && pawn.CanReach(w, PathEndMode.Touch, Danger.Deadly, true) && (pawn.Faction.HostileTo(Faction.OfPlayer) || pawn.Faction == Faction.OfPlayer || !pawn.Map.areaManager.Home[w.Position]); // generate a list of all weapons (this includes melee weapons) List <Thing> allWeapons = ( from w in pawn.Map.listerThings.ThingsInGroup(ThingRequestGroup.HaulableAlways) where validatorWS(w) orderby w.MarketValue - w.Position.DistanceToSquared(pawn.Position) * 2f descending select w ).ToList(); // now just get the ranged weapons out... List <Thing> rangedWeapons = allWeapons.Where(w => w.def.IsRangedWeapon).ToList(); if (!rangedWeapons.NullOrEmpty()) { foreach (Thing thing in rangedWeapons) { if (thing.TryGetComp <CompAmmoUser>() == null) { // pickup a non-CE ranged weapon... int numToThing = 0; if (inventory.CanFitInInventory(thing, out numToThing)) { return(JobMaker.MakeJob(JobDefOf.Equip, thing)); } } else { // pickup a CE ranged weapon... List <ThingDef> thingDefAmmoList = thing.TryGetComp <CompAmmoUser>().Props.ammoSet.ammoTypes.Select(g => g.ammo as ThingDef).ToList(); Predicate <Thing> validatorA = (Thing t) => t.def.category == ThingCategory.Item && t is AmmoThing && pawn.CanReserve(t, 1) && pawn.Position.InHorDistOf(t.Position, 25f) && pawn.CanReach(t, PathEndMode.Touch, Danger.Deadly, true) && (pawn.Faction.HostileTo(Faction.OfPlayer) || pawn.Faction == Faction.OfPlayer || !pawn.Map.areaManager.Home[t.Position]); List <Thing> thingAmmoList = ( from t in pawn.Map.listerThings.ThingsInGroup(ThingRequestGroup.HaulableAlways) where validatorA(t) select t ).ToList(); if (thingAmmoList.Count > 0 && thingDefAmmoList.Count > 0) { int desiredStackSize = thing.TryGetComp <CompAmmoUser>().Props.magazineSize * 2; Thing th = thingAmmoList.FirstOrDefault(x => thingDefAmmoList.Contains(x.def) && x.stackCount > desiredStackSize); if (th != null) { int numToThing = 0; if (inventory.CanFitInInventory(thing, out numToThing)) { return(JobMaker.MakeJob(JobDefOf.Equip, thing)); } } } } } } // else if no ranged weapons with nearby ammo was found, lets consider a melee weapon. if (allWeapons != null && allWeapons.Count > 0) { // since we don't need to worry about ammo, just pick one. Thing meleeWeapon = allWeapons.FirstOrDefault(w => !w.def.IsRangedWeapon && w.def.IsMeleeWeapon); if (meleeWeapon != null) { return(JobMaker.MakeJob(JobDefOf.Equip, meleeWeapon)); } } } } // Find ammo if ((priority == WorkPriority.Ammo || priority == WorkPriority.LowAmmo) && primaryAmmoUserWithInventoryCheck != null) { List <ThingDef> curAmmoList = (from AmmoLink g in primaryAmmoUserWithInventoryCheck.Props.ammoSet.ammoTypes select g.ammo as ThingDef).ToList(); if (curAmmoList.Count > 0) { Predicate <Thing> validator = (Thing t) => t is AmmoThing && pawn.CanReserve(t, 1) && pawn.CanReach(t, PathEndMode.Touch, Danger.Deadly, true) && ((pawn.Faction.IsPlayer && !ForbidUtility.IsForbidden(t, pawn)) || (!pawn.Faction.IsPlayer && pawn.Position.InHorDistOf(t.Position, 35f))) && (pawn.Faction.HostileTo(Faction.OfPlayer) || pawn.Faction == Faction.OfPlayer || !pawn.Map.areaManager.Home[t.Position]); List <Thing> curThingList = ( from t in pawn.Map.listerThings.ThingsInGroup(ThingRequestGroup.HaulableAlways) where validator(t) select t ).ToList(); foreach (Thing th in curThingList) { foreach (ThingDef thd in curAmmoList) { if (thd == th.def) { //Defence from low count loot spam float thw = (th.GetStatValue(CE_StatDefOf.Bulk)) * th.stackCount; if (thw > 0.5f) { if (pawn.Faction.IsPlayer) { int SearchRadius = 0; if (priority == WorkPriority.LowAmmo) { SearchRadius = 70; } else { SearchRadius = 30; } Thing closestThing = GenClosest.ClosestThingReachable( pawn.Position, pawn.Map, ThingRequest.ForDef(th.def), PathEndMode.ClosestTouch, TraverseParms.For(pawn, Danger.None, TraverseMode.ByPawn), SearchRadius, x => !x.IsForbidden(pawn) && pawn.CanReserve(x)); if (closestThing != null) { int numToCarry = 0; if (inventory.CanFitInInventory(th, out numToCarry)) { Job job = JobMaker.MakeJob(JobDefOf.TakeInventory, th); job.count = numToCarry; return(job); } } } else { int numToCarry = 0; if (inventory.CanFitInInventory(th, out numToCarry)) { Job job = JobMaker.MakeJob(JobDefOf.TakeInventory, th); job.count = Mathf.RoundToInt(numToCarry * 0.8f); return(job); } } } } } } } } /* * if (!pawn.Faction.IsPlayer && pawn.apparel != null && priority == WorkPriority.Apparel) * { * if (!pawn.apparel.BodyPartGroupIsCovered(BodyPartGroupDefOf.Torso)) * { * Apparel apparel = this.FindGarmentCoveringPart(pawn, BodyPartGroupDefOf.Torso); * if (apparel != null) * { * int numToapparel = 0; * if (inventory.CanFitInInventory(apparel, out numToapparel)) * { * return JobMaker.MakeJob(JobDefOf.Wear, apparel) * { * ignoreForbidden = true * }; * } * } * } * if (!pawn.apparel.BodyPartGroupIsCovered(BodyPartGroupDefOf.Legs)) * { * Apparel apparel2 = this.FindGarmentCoveringPart(pawn, BodyPartGroupDefOf.Legs); * if (apparel2 != null) * { * int numToapparel2 = 0; * if (inventory.CanFitInInventory(apparel2, out numToapparel2)) * { * return JobMaker.MakeJob(JobDefOf.Wear, apparel2) * { * ignoreForbidden = true * }; * } * } * } * if (!pawn.apparel.BodyPartGroupIsCovered(BodyPartGroupDefOf.FullHead)) * { * Apparel apparel3 = this.FindGarmentCoveringPart(pawn, BodyPartGroupDefOf.FullHead); * if (apparel3 != null) * { * int numToapparel3 = 0; * if (inventory.CanFitInInventory(apparel3, out numToapparel3)) * { * return JobMaker.MakeJob(JobDefOf.Wear, apparel3) * { * ignoreForbidden = true, * locomotionUrgency = LocomotionUrgency.Sprint * }; * } * } * } * } */ return(null); } return(null); }
protected override Job TryGiveJob(Pawn pawn) { Corpse corpse = null; Building_Grave building_Grave = null; //see if there's a corpse laying around or available for digging up if (Rand.Range(0f, 1f) > 0.05f) { corpse = (Corpse)GenClosest.ClosestThingReachable(pawn.Position, pawn.Map, ThingRequest.ForGroup(ThingRequestGroup.Corpse), PathEndMode.ClosestTouch, TraverseParms.For(pawn, Danger.Deadly, TraverseMode.ByPawn, false), 9999f, delegate(Thing x) { Corpse corpse2 = (Corpse)x; return(corpse2.Spawned && corpse2.InnerPawn.BodySize <= pawn.RaceProps.maxPreyBodySize); }, null, 0, -1, false, RegionType.Set_Passable, false); if (!pawn.CanReserveAndReach(corpse, PathEndMode.Touch, Danger.Deadly, 1, -1, null, false)) { return(null); } } else { corpse = GetClosestCorpseToDigUp(pawn); building_Grave = corpse?.ParentHolder as Building_Grave; if (building_Grave != null) { if (!pawn.CanReserveAndReach(building_Grave, PathEndMode.InteractionCell, Danger.Deadly, 1, -1, null, false)) { return(null); } } } return(new Job(CatsAreJerks_JobDefOf.DeliverKill, corpse, building_Grave) { count = 1 }); }
public static Thing ClosestThingReachable_JT(IntVec3 root, ThingRequest thingReq, PathEndMode peMode, TraverseParms traverseParams, float maxDistance = 9999f, Predicate <Thing> validator = null, IEnumerable <Thing> customGlobalSearchSet = null, int searchRegionsMax = -1, bool forceGlobalSearch = false) { //customGlobalSearchSet in context of hauling is list of things to be hauled //forceGlobalSearch is true when customGlobalSearchSet is not null //searchRegionMax is only used for cleaning ProfilerThreadCheck.BeginSample("ClosestThingReachable"); //Guessing if searchRegionsMax is > 0, customGlobalSearchSet is not suppose to be used. if (searchRegionsMax > 0 && customGlobalSearchSet != null && !forceGlobalSearch) { Log.ErrorOnce("searchRegionsMax > 0 && customGlobalSearchSet != null && !forceGlobalSearch. customGlobalSearchSet will never be used.", 634984); } //There is no null check for thingReq, always not null? //if thingReq group == nothing || //if there is thingReq and customGlobalSearchSet is null and there are things matching thingReq if (EarlyOutSearch_JT(root, thingReq, customGlobalSearchSet)) { ProfilerThreadCheck.EndSample(); return(null); } //Use either searchRegionsMax or customGlobalSearchSet //We're interested in thingReq.group == HaulableEver, HaulableAlways, HaulableEverOrMinifiable //This means customGlobalSearch has to have something (when there are such items on map) --> correct //Actual stuff begins? Thing thing = null; //IsUndefined == singleDef == null && thingReq group == Undefined if (!thingReq.IsUndefined) { //The debug bellow only resuted in group == Pawn, 7 times with 3 pawns all set only to haul, perhaps dogs loving? //Therefore probably ignore this if //Log.Message("First if was called. " + thingReq.group.ToString()); //Hauling: searchRegionsMax should be -1 --> maxRegions = 30 int maxRegions = (searchRegionsMax <= 0) ? 30 : searchRegionsMax; thing = GenClosest.RegionwiseBFSWorker(root, thingReq, peMode, traverseParams, validator, null, 0, maxRegions, maxDistance); } if (thing == null && (searchRegionsMax < 0 || forceGlobalSearch)) { //validator = (Thing t) => !t.IsForbidden(pawn) && scanner.HasJobOnThing(pawn, t); //Debug bellow gives thingReq group to be Undefined, skips first //Log.Message("First if resulted in null " + thingReq.group.ToString()); Predicate <Thing> validator2 = (Thing t) => root.CanReach(t, peMode, traverseParams) && (validator == null || validator(t)); IEnumerable <Thing> searchSet = customGlobalSearchSet ?? Find.ListerThings.ThingsMatching(thingReq); //Main start of my code List <Thing> degrade = new List <Thing>(); List <Thing> undegrade = new List <Thing>(); //Seperate into degrade or not foreach (Thing t in searchSet) { if (t.GetStatValue(StatDefOf.DeteriorationRate) > 0) { degrade.Add(t); } else { undegrade.Add(t); } } //Loop through all haul areas in order foreach (Area a in AreaFinder.getHaulAreas()) { //Check if got degradable item thing = GenClosest.ClosestThing_Global(root, AreaFinder.searcher(a, degrade), maxDistance, validator2); if (thing != null) { break; } //Check if got undegradable item thing = GenClosest.ClosestThing_Global(root, AreaFinder.searcher(a, undegrade), maxDistance, validator2); if (thing != null) { break; } } if (thing == null) { thing = GenClosest.ClosestThing_Global(root, degrade, maxDistance, validator2); if (thing == null) { thing = GenClosest.ClosestThing_Global(root, undegrade, maxDistance, validator2); } } /* old 50 cell code * thing = GenClosest.ClosestThing_Global(root, degrade, 50f, validator2); //If there is degradable with 50 cells * if (thing == null) * { * thing = GenClosest.ClosestThing_Global(root, undegrade, 50f, validator2);//If there is undegradable with 50 cells * if (thing == null) * { * thing = GenClosest.ClosestThing_Global(root, degrade, maxDistance, validator2); //If there is degradable * if (thing == null) * { * thing = GenClosest.ClosestThing_Global(root, undegrade, maxDistance, validator2); //If there is undegradable * } * } * } */ //Main end of my code } /* * if (thing != null) * { * Log.Message(thing.def.defName); * } * else { * Log.Message("Resulted in null"); * }*/ ProfilerThreadCheck.EndSample(); return(thing); }
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 != RimWorld.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.relatedPawns) && pawn3.Downed); }; pawn2 = (Pawn)GenClosest.ClosestThingReachable(pawn.Position, pawn.Map, ThingRequest.ForDef(pawn.def), 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); }; pawn2 = (Pawn)GenClosest.ClosestThingReachable(pawn.Position, pawn.Map, ThingRequest.ForDef(pawn.def), 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.def.race.Humanlike && * corpse.InnerPawn.PawnListed(relatedPawns); * }; * Corpse corpse2 = (Corpse)GenClosest.ClosestThing_Global_Reachable(pawn.Position, pawn.Map, pawn.Map.listerThings.ThingsInGroup(ThingRequestGroup.Corpse), PathEndMode.ClosestTouch, TraverseParms.For(pawn, Danger.Deadly, TraverseMode.ByPawn, false), maxSearchDistance, validator, null); * 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.Succeeded); * * return; * }*/ return(null); }
public static Thing BestWaterSourceOnMap(Pawn getter, Pawn eater, bool priorQuality, bool allowBuilding, WaterPreferability maxPref = WaterPreferability.ClearWater, bool allowDrug = false, bool allowForbidden = false, bool allowSociallyImproper = false) { if (!getter.CanManipulate() && getter != eater) { // 取得者は操作不可、取得者と摂取者が違う // →マップから取得して持ち運ぶことができない // →エラー Log.Error(string.Concat(new object[] { getter, " tried to find food to bring to ", eater, " but ", getter, " is incapable of Manipulation." })); return(null); } Predicate <Thing> waterValidator = (t) => { // 禁止されている&禁止を無視して取得してはいけない if (!allowForbidden && t.IsForbidden(getter)) { return(false); } // ドラッグ禁止&対象はドラッグ if (!allowDrug && t.def.IsDrug) { return(false); } // 取得者が予約できない if (!getter.CanReserve(t)) { return(false); } var comp = t.TryGetComp <CompWaterSource>(); // 水源として使用できない if (comp == null || !comp.IsWaterSource) { return(false); } // 食べられるものは飲み物としては選ばれない if (t.def.IsIngestible) { return(false); } // 操作が必要なのに操作できない if (comp.NeedManipulate && !getter.CanManipulate()) { return(false); } var waterTypeDef = MizuDef.Dic_WaterTypeDef[comp.WaterType]; if (comp.SourceType == CompProperties_WaterSource.SourceType.Item) { // 水分がない if (!t.CanGetWater()) { return(false); } // 水分を持っている=水アイテムである WaterPreferability waterPreferability = t.GetWaterPreferability(); // 水の品質が範囲外 if (waterPreferability < WaterPreferability.SeaWater || waterPreferability > maxPref) { return(false); } // 現在飲める状態には無い if (!t.CanDrinkWaterNow()) { return(false); } // 入植者は囚人部屋のアイテムを扱えないことがあるが、そのことに関するチェックでダメならfalse if (!MizuUtility.IsWaterSourceOnMapSociallyProper(t, getter, eater, allowSociallyImproper)) { return(false); } // 取得者がそれに気づいていない if (!getter.AnimalAwareOf(t)) { return(false); } return(true); } else if (comp.SourceType == CompProperties_WaterSource.SourceType.Building) { // 取得者と摂取者が異なる(自分で飲みに行く必要がある) if (getter != eater) { return(false); } var drinkWaterBuilding = t as IBuilding_DrinkWater; // 水汲みに使えない if (drinkWaterBuilding == null) { return(false); } // 水を飲む人が飲めない(能力が無い、水の量がない) if (!drinkWaterBuilding.CanDrinkFor(eater)) { return(false); } // 最大水質を超えていたらダメ if (waterTypeDef.waterPreferability > maxPref) { return(false); } // 野生人?(派閥所属なし?)はダメ if (eater.IsWildMan()) { return(false); } // 自陣営or自陣営のホストの設備でなければダメ // 動物でない場合は、という条件を追加 if (!eater.RaceProps.Animal && t.Faction != eater.Faction && t.Faction != eater.HostFaction) { return(false); } // 使えない状態はダメ if (!drinkWaterBuilding.IsActivated) { return(false); } // 入植者は囚人部屋のアイテムを扱えないことがあるが、そのことに関するチェックでダメならfalse if (!MizuUtility.IsWaterSourceOnMapSociallyProper(t, getter, eater, allowSociallyImproper)) { return(false); } if (t.def.hasInteractionCell == true) { // 使用場所がある if (!t.InteractionCell.Standable(t.Map) || !eater.Map.reachability.CanReachNonLocal(getter.Position, new TargetInfo(t.InteractionCell, t.Map, false), PathEndMode.OnCell, TraverseParms.For(getter, Danger.Some, TraverseMode.ByPawn, false))) { // 使用場所に立てない or 使用場所まで行けない return(false); } } else { // 使用場所が無い if (!getter.Map.reachability.CanReachNonLocal(getter.Position, new TargetInfo(t.Position, t.Map, false), PathEndMode.ClosestTouch, TraverseParms.For(getter, Danger.Some, TraverseMode.ByPawn, false))) { // その設備にタッチできない return(false); } } return(true); } // それ以外 return(false); }; if (getter.RaceProps.Humanlike) { // 取得者はHumanlikeである // →条件を満たすものの中から最適な物を探す return(MizuUtility.SpawnedWaterSearchInnerScan( eater, getter.Position, getter.Map.listerThings.ThingsInGroup(ThingRequestGroup.Everything).FindAll((t) => { if (t.CanDrinkWaterNow()) { return true; } var building = t as IBuilding_DrinkWater; if (building != null && building.CanDrinkFor(eater)) { return true; } return false; }), PathEndMode.ClosestTouch, TraverseParms.For(getter), priorQuality, 9999f, waterValidator)); } // 取得者はHumanlikeではない // プレイヤー派閥に所属しているかどうかでリージョン?数を変える int searchRegionsMax = 30; if (getter.Faction == Faction.OfPlayer) { searchRegionsMax = 100; } HashSet <Thing> filtered = new HashSet <Thing>(); foreach (Thing current in GenRadial.RadialDistinctThingsAround(getter.Position, getter.Map, 2f, true)) { // 自分を中心に半径2以内の物をチェック Pawn pawn = current as Pawn; if (pawn != null && pawn != getter && pawn.RaceProps.Animal && pawn.CurJob != null && pawn.CurJob.def == MizuDef.Job_DrinkWater && 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 = (t) => { // アイテムが条件を満たしていない if (!waterValidator(t)) { return(false); } // すぐ近くで他の動物が飲んでいる水のリストに入っていない if (filtered.Contains(t)) { return(false); } // 水の品質が最低値未満 if (t.GetWaterPreferability() < WaterPreferability.SeaWater) { return(false); } return(true); }; // 指定の条件下でアクセスできるものを探す Thing thing = null; // 水アイテムから thing = GenClosest.ClosestThingReachable( getter.Position, getter.Map, ThingRequest.ForGroup(ThingRequestGroup.HaulableEver), PathEndMode.ClosestTouch, TraverseParms.For(getter), 9999f, predicate, null, 0, searchRegionsMax, false, RegionType.Set_Passable, ignoreEntirelyForbiddenRegions); if (thing != null) { return(thing); } // 水汲み設備 thing = GenClosest.ClosestThingReachable( getter.Position, getter.Map, ThingRequest.ForGroup(ThingRequestGroup.BuildingArtificial), PathEndMode.ClosestTouch, TraverseParms.For(getter), 9999f, predicate, null, 0, searchRegionsMax, false, RegionType.Set_Passable, ignoreEntirelyForbiddenRegions); if (thing != null) { return(thing); } // 条件を変えて再探索 // 水アイテム thing = GenClosest.ClosestThingReachable( getter.Position, getter.Map, ThingRequest.ForGroup(ThingRequestGroup.HaulableEver), PathEndMode.ClosestTouch, TraverseParms.For(getter), 9999f, waterValidator, // ここが変わった null, 0, searchRegionsMax, false, RegionType.Set_Passable, ignoreEntirelyForbiddenRegions); if (thing != null) { return(thing); } // 水汲み設備 thing = GenClosest.ClosestThingReachable( getter.Position, getter.Map, ThingRequest.ForGroup(ThingRequestGroup.BuildingArtificial), PathEndMode.ClosestTouch, TraverseParms.For(getter), 9999f, waterValidator, // ここが変わった null, 0, searchRegionsMax, false, RegionType.Set_Passable, ignoreEntirelyForbiddenRegions); if (thing != null) { return(thing); } return(null); }
private Thing FindClosestCloth(Pawn pawn) { Predicate <Thing> validator = (Thing x) => !x.IsForbidden(pawn) && pawn.CanReserve(x, 1); return(GenClosest.ClosestThingReachable(pawn.Position, pawn.Map, ThingRequest.ForDef(this.parent.Stuff), PathEndMode.InteractionCell, TraverseParms.For(pawn, pawn.NormalMaxDanger(), TraverseMode.ByPawn, false), 9999f, validator, null, -1, -1, false)); }
private static bool TryFindBestTaskIngredients(ActivityTask task, Pawn pawn, Thing giver, List <ThingCount> chosenIngThings) { chosenIngThings.Clear(); newRelevantThings.Clear(); if (task.ActivityTaskDef.ThingDefsCount.Count() == 0) { return(true); } IntVec3 rootCell = GetGiverRootCell(giver, pawn); Region rootReg = rootCell.GetRegion(pawn.Map, RegionType.Set_Passable); if (rootReg == null) { return(false); } relevantThings.Clear(); processedThings.Clear(); bool foundAll = false; Predicate <Thing> baseValidator = (Predicate <Thing>)(t => { if (t.Spawned && !t.IsForbidden(pawn) && ((double)(t.Position - giver.Position).LengthHorizontalSquared < (double)task.IngredientSearchRadius * (double)task.IngredientSearchRadius && task.ThingFilter.Allows(t.def))) { return(pawn.CanReserve((LocalTargetInfo)t, 1, -1, (ReservationLayerDef)null, false)); } return(false); }); TraverseParms traverseParams = TraverseParms.For(pawn, Danger.Deadly, TraverseMode.ByPawn, false); RegionEntryPredicate entryCondition = (RegionEntryPredicate)((from, r) => r.Allows(traverseParams, false)); int adjacentRegionsAvailable = rootReg.Neighbors.Count <Region>((Func <Region, bool>)(region => entryCondition(rootReg, region))); int regionsProcessed = 0; processedThings.AddRange <Thing>(relevantThings); RegionProcessor regionProcessor = (RegionProcessor)(r => { List <Thing> thingList = r.ListerThings.ThingsMatching(ThingRequest.ForGroup(ThingRequestGroup.HaulableEver)); for (int index = 0; index < thingList.Count; ++index) { Thing thing = thingList[index]; if (!processedThings.Contains(thing) && ReachabilityWithinRegion.ThingFromRegionListerReachable(thing, r, PathEndMode.ClosestTouch, pawn) && baseValidator(thing)) { newRelevantThings.Add(thing); processedThings.Add(thing); } } ++regionsProcessed; if (newRelevantThings.Count > 0 && regionsProcessed > adjacentRegionsAvailable) { Comparison <Thing> comparison = (Comparison <Thing>)((t1, t2) => ((float)(t1.Position - rootCell).LengthHorizontalSquared).CompareTo((float)(t2.Position - rootCell).LengthHorizontalSquared)); newRelevantThings.Sort(comparison); relevantThings.AddRange((IEnumerable <Thing>)newRelevantThings); newRelevantThings.Clear(); if (TryFindBestBillIngredientsInSet(relevantThings, task, chosenIngThings)) { foundAll = true; return(true); } } return(false); }); RegionTraverser.BreadthFirstTraverse(rootReg, entryCondition, regionProcessor, 99999, RegionType.Set_Passable); relevantThings.Clear(); newRelevantThings.Clear(); processedThings.Clear(); ingredientsOrdered.Clear(); return(foundAll); }
public static Building_Bed FindBedFor(Pawn sleeper, Pawn traveler, bool sleeperWillBePrisoner, bool checkSocialProperness, bool ignoreOtherReservations = false) { if (HealthAIUtility.ShouldSeekMedicalRest(sleeper)) { if (sleeper.InBed() && sleeper.CurrentBed().Medical) { Building_Bed bedThing = sleeper.CurrentBed(); Pawn pawn = sleeper; Pawn pawn2 = traveler; bool flag = sleeperWillBePrisoner; bool checkSocialProperness2 = checkSocialProperness; bool flag2 = ignoreOtherReservations; if (RestUtility.IsValidBedFor(bedThing, pawn, pawn2, flag, checkSocialProperness2, false, flag2)) { return(sleeper.CurrentBed()); } } for (int i = 0; i < RestUtility.bedDefsBestToWorst_Medical.Count; i++) { ThingDef thingDef = RestUtility.bedDefsBestToWorst_Medical[i]; if (RestUtility.CanUseBedEver(sleeper, thingDef)) { for (int j = 0; j < 2; j++) { Danger maxDanger = (j != 0) ? Danger.Deadly : Danger.None; Building_Bed building_Bed = (Building_Bed)GenClosest.ClosestThingReachable(sleeper.Position, sleeper.Map, ThingRequest.ForDef(thingDef), PathEndMode.OnCell, TraverseParms.For(traveler, Danger.Deadly, TraverseMode.ByPawn, false), 9999f, delegate(Thing b) { bool result; if (((Building_Bed)b).Medical && b.Position.GetDangerFor(sleeper, sleeper.Map) <= maxDanger) { Pawn sleeper2 = sleeper; Pawn traveler2 = traveler; bool sleeperWillBePrisoner2 = sleeperWillBePrisoner; bool checkSocialProperness3 = checkSocialProperness; bool ignoreOtherReservations2 = ignoreOtherReservations; result = RestUtility.IsValidBedFor(b, sleeper2, traveler2, sleeperWillBePrisoner2, checkSocialProperness3, false, ignoreOtherReservations2); } else { result = false; } return(result); }, null, 0, -1, false, RegionType.Set_Passable, false); if (building_Bed != null) { return(building_Bed); } } } } } if (sleeper.ownership != null && sleeper.ownership.OwnedBed != null) { Building_Bed bedThing = sleeper.ownership.OwnedBed; Pawn pawn2 = sleeper; Pawn pawn = traveler; bool flag2 = sleeperWillBePrisoner; bool checkSocialProperness2 = checkSocialProperness; bool flag = ignoreOtherReservations; if (RestUtility.IsValidBedFor(bedThing, pawn2, pawn, flag2, checkSocialProperness2, false, flag)) { return(sleeper.ownership.OwnedBed); } } DirectPawnRelation directPawnRelation = LovePartnerRelationUtility.ExistingMostLikedLovePartnerRel(sleeper, false); if (directPawnRelation != null) { Building_Bed ownedBed = directPawnRelation.otherPawn.ownership.OwnedBed; if (ownedBed != null) { Building_Bed bedThing = ownedBed; Pawn pawn = sleeper; Pawn pawn2 = traveler; bool flag = sleeperWillBePrisoner; bool checkSocialProperness2 = checkSocialProperness; bool flag2 = ignoreOtherReservations; if (RestUtility.IsValidBedFor(bedThing, pawn, pawn2, flag, checkSocialProperness2, false, flag2)) { return(ownedBed); } } } for (int k = 0; k < 2; k++) { Danger maxDanger = (k != 0) ? Danger.Deadly : Danger.None; for (int l = 0; l < RestUtility.bedDefsBestToWorst_RestEffectiveness.Count; l++) { ThingDef thingDef2 = RestUtility.bedDefsBestToWorst_RestEffectiveness[l]; if (RestUtility.CanUseBedEver(sleeper, thingDef2)) { Building_Bed building_Bed2 = (Building_Bed)GenClosest.ClosestThingReachable(sleeper.Position, sleeper.Map, ThingRequest.ForDef(thingDef2), PathEndMode.OnCell, TraverseParms.For(traveler, Danger.Deadly, TraverseMode.ByPawn, false), 9999f, delegate(Thing b) { bool result; if (!((Building_Bed)b).Medical && b.Position.GetDangerFor(sleeper, sleeper.Map) <= maxDanger) { Pawn sleeper2 = sleeper; Pawn traveler2 = traveler; bool sleeperWillBePrisoner2 = sleeperWillBePrisoner; bool checkSocialProperness3 = checkSocialProperness; bool ignoreOtherReservations2 = ignoreOtherReservations; result = RestUtility.IsValidBedFor(b, sleeper2, traveler2, sleeperWillBePrisoner2, checkSocialProperness3, false, ignoreOtherReservations2); } else { result = false; } return(result); }, null, 0, -1, false, RegionType.Set_Passable, false); if (building_Bed2 != null) { return(building_Bed2); } } } } return(null); }
public Toil CarryBookToSeat(Pawn pawn) { Toil carryBook = new Toil(); IntVec3 position; carryBook.initAction = delegate { Predicate <Thing> validator = delegate(Thing t) { bool result; if (t.def.building == null || !t.def.building.isSittable) { result = false; } else { if (t.IsForbidden(pawn)) { result = false; } else { if (!carryBook.actor.CanReserve(t)) { result = false; } else { if (!t.IsSociallyProper(carryBook.actor)) { result = false; } else { if (t.IsBurning()) { result = false; } else { bool flag = false; for (int i = 0; i < 4; i++) { Building edifice = (t.Position + GenAdj.CardinalDirections[i]).GetEdifice(); if (edifice != null && (edifice.def.surfaceType == SurfaceType.Eat || edifice.def.surfaceType == SurfaceType.Item)) { flag = true; break; } } result = flag; } } } } } return(result); }; Thing thing = GenClosest.ClosestThingReachable(carryBook.actor.Position, ThingRequest.ForGroup(ThingRequestGroup.BuildingArtificial), PathEndMode.OnCell, TraverseParms.For(carryBook.actor), 25f, validator, null, 1); if (thing != null) { position = thing.Position; Find.Reservations.Reserve(carryBook.actor, thing); } else { position = RCellFinder.SpotToChewStandingNear(carryBook.actor, carryBook.actor.CurJob.targetA.Thing); } Find.PawnDestinationManager.ReserveDestinationFor(carryBook.actor, position); carryBook.actor.pather.StartPath(position, PathEndMode.OnCell); }; carryBook.defaultCompleteMode = ToilCompleteMode.PatherArrival; return(carryBook); }
public static Building_Bed FindPatientBedFor(Pawn pawn) { Predicate <Thing> medBedValidator = delegate(Thing t) { Building_Bed building_Bed2 = t as Building_Bed; return(building_Bed2 != null && (building_Bed2.Medical || !building_Bed2.def.building.bed_humanlike) && RestUtility.IsValidBedFor(building_Bed2, pawn, pawn, pawn.IsPrisoner, false, true, false)); }; Building_Bed result; if (pawn.InBed() && medBedValidator(pawn.CurrentBed())) { result = pawn.CurrentBed(); } else { for (int i = 0; i < 2; i++) { Danger maxDanger = (i != 0) ? Danger.Deadly : Danger.None; 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) => b.Position.GetDangerFor(pawn, pawn.Map) <= maxDanger && medBedValidator(b), null, 0, -1, false, RegionType.Set_Passable, false); if (building_Bed != null) { return(building_Bed); } } result = RestUtility.FindBedFor(pawn); } return(result); }
protected override IntVec3 GetWanderRoot(Pawn pawn) { Predicate <Thing> validator = delegate(Thing t) { bool result; if (((Pawn)t).RaceProps != pawn.RaceProps || t == pawn) { result = false; } else if (t.Faction != pawn.Faction) { result = false; } else if (t.Position.IsForbidden(pawn)) { result = false; } else if (!pawn.CanReach(t, PathEndMode.OnCell, Danger.Deadly, false, TraverseMode.ByPawn)) { result = false; } else if (Rand.Value < 0.5f) { result = false; } else { List <Pawn> allPawnsSpawned = pawn.Map.mapPawns.AllPawnsSpawned; for (int i = 0; i < allPawnsSpawned.Count; i++) { Pawn pawn2 = allPawnsSpawned[i]; if (pawn2.RaceProps.Humanlike && (pawn2.Position - t.Position).LengthHorizontalSquared < 225) { return(false); } } result = true; } return(result); }; Thing thing = GenClosest.ClosestThingReachable(pawn.Position, pawn.Map, ThingRequest.ForGroup(ThingRequestGroup.Pawn), PathEndMode.OnCell, TraverseParms.For(pawn, Danger.Deadly, TraverseMode.ByPawn, false), 35f, validator, null, 13, -1, false, RegionType.Set_Passable, false); IntVec3 position; if (thing != null) { position = thing.Position; } else { position = pawn.Position; } return(position); }
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; } }
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, 1, -1, null, false) && !pawn3.IsForbidden(pawn) && !GenAI.EnemyIsNear(pawn3, 25f)); }; Pawn pawn2 = (Pawn)GenClosest.ClosestThingReachable(pawn.Position, pawn.Map, ThingRequest.ForGroup(ThingRequestGroup.Pawn), PathEndMode.OnCell, TraverseParms.For(pawn, Danger.Deadly, TraverseMode.ByPawn, false), this.radius, validator, null, 0, -1, false, RegionType.Set_Passable, false); Job result; if (pawn2 == null) { result = null; } else { Building_Bed building_Bed = RestUtility.FindBedFor(pawn2, pawn, pawn2.HostFaction == pawn.Faction, false, false); if (building_Bed == null || !pawn2.CanReserve(building_Bed, 1, -1, null, false)) { result = null; } else { result = new Job(JobDefOf.Rescue, pawn2, building_Bed) { count = 1 }; } } return(result); }
// used to manually re-arm turrets static void Postfix(WorkGiver_ReloadTurret __instance, ref bool __result, Pawn pawn, Thing t, bool forced) { Building_TurretGunCE turret = t as Building_TurretGunCE; if (__result == false && turret != null && !turret.def.hasInteractionCell) { if (WorldComp.HasStorages(turret.Map) && CombatExtendedUtil.HasAmmo(turret.CompAmmo.SelectedAmmo)) { WS = GenClosest.ClosestThingReachable(turret.Position, turret.Map, ThingRequest.ForDef(WorldComp.WeaponStorageDef), Verse.AI.PathEndMode.ClosestTouch, TraverseParms.For(pawn, pawn.NormalMaxDanger(), TraverseMode.ByPawn, false), 100) as Building; __result = WS != null; } } }
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.owners.NullOrEmpty() || platform.owners.Contains(targetPawn))) { CompFlickable flickable = platform.TryGetComp <CompFlickable>(); if (flickable != null && !flickable.SwitchIsOn) { return false; } return true; } return false; })); }
// RimWorld.FloatMenuMakerMap /* * PostFix * * This code adds to the float menu list. * * Adds: * + Force straitjacket on _____ * + Help _____ out of straitjacket * */ public static void AddHumanlikeOrdersPostFix(Vector3 clickPos, Pawn pawn, List <FloatMenuOption> opts) { IntVec3 c = IntVec3.FromVector3(clickPos); foreach (Thing current in c.GetThingList(pawn.Map)) { if (current is Pawn target && pawn != null && pawn != target && !pawn.Dead && !pawn.Downed) { //We sadly can't handle aggro mental states or non-humanoids. if ((target?.RaceProps?.Humanlike ?? false) && !target.InAggroMentalState) { //Let's proceed if our 'actor' is capable of manipulation if (pawn.health.capacities.CapableOf(PawnCapacityDefOf.Manipulation)) { //Does the target have a straitjacket? //We can help them remove the straitjacket. if (target?.apparel?.WornApparel?.FirstOrDefault(x => x.def == StraitjacketDefOf.ROM_Straitjacket) != null) { if (!pawn.CanReach(c, PathEndMode.OnCell, Danger.Deadly, false, TraverseMode.ByPawn)) { opts.Add(new FloatMenuOption("CannotRemoveStraitjacket".Translate() + " (" + "NoPath".Translate() + ")", null, MenuOptionPriority.Default, null, null, 0f, null, null)); } else if (!pawn.CanReserve(target, 1)) { opts.Add(new FloatMenuOption("CannotRemoveStraitjacket".Translate() + ": " + "Reserved".Translate(), null, MenuOptionPriority.Default, null, null, 0f, null, null)); } else { Action action = delegate { Job job = new Job(StraitjacketDefOf.ROM_TakeOffStraitjacket, target); job.count = 1; pawn.jobs.TryTakeOrderedJob(job); }; opts.Add(new FloatMenuOption("RemoveStraitjacket".Translate(new object[] { target.LabelCap }), action, MenuOptionPriority.High, null, target, 0f, null, null)); } } //We can put one on! else { if (pawn.Map.listerThings.ThingsInGroup(ThingRequestGroup.Apparel).FirstOrDefault((Thing x) => x.def == StraitjacketDefOf.ROM_Straitjacket) != null) { if (!pawn.CanReach(c, PathEndMode.OnCell, Danger.Deadly, false, TraverseMode.ByPawn)) { opts.Add(new FloatMenuOption("CannotForceStraitjacket".Translate() + " (" + "NoPath".Translate() + ")", null, MenuOptionPriority.Default, null, null, 0f, null, null)); } else if (!pawn.CanReserve(target, 1)) { opts.Add(new FloatMenuOption("CannotForceStraitjacket".Translate() + ": " + "Reserved".Translate(), null, MenuOptionPriority.Default, null, null, 0f, null, null)); } else { Action action = delegate { Thing straitjacket = GenClosest.ClosestThingReachable(pawn.Position, pawn.Map, ThingRequest.ForDef(StraitjacketDefOf.ROM_Straitjacket), PathEndMode.Touch, TraverseParms.For(pawn)); Job job = new Job(StraitjacketDefOf.ROM_ForceIntoStraitjacket, target, straitjacket); job.count = 1; job.locomotionUrgency = LocomotionUrgency.Sprint; pawn.jobs.TryTakeOrderedJob(job); }; opts.Add(new FloatMenuOption("ForceStraitjacketUpon".Translate(new object[] { target.LabelCap }), action, MenuOptionPriority.High, null, target, 0f, null, null)); } } } } } } } }
protected override Job TryGiveJob(Pawn pawn) { if (pawn.Downed) { return(null); } Need_Energy energy = pawn.needs.TryGetNeed <Need_Energy>(); if (energy == null) { return(null); } if (energy.CurLevelPercentage >= Need_Energy.rechargePercentage) { return(null); } if (Find.TickManager.TicksGame < GetLastTryTick(pawn) + 2500) { return(null); } SetLastTryTick(pawn, Find.TickManager.TicksGame); //See if we got a nearby powernet to tap into. Thing closestPowerSource = EnergyNeedUtility.ClosestPowerSource(pawn); if (closestPowerSource != null) { Building building = closestPowerSource as Building; if (closestPowerSource != null && building != null && building.PowerComp != null && building.PowerComp.PowerNet.CurrentStoredEnergy() > 50f) { //Find a suitable spot to drain from. IntVec3 drainSpot = closestPowerSource.Position; //Give out job to go out and tap it. if (drainSpot.Walkable(pawn.Map) && drainSpot.InAllowedArea(pawn) && pawn.CanReserve(new LocalTargetInfo(drainSpot)) && pawn.CanReach(drainSpot, PathEndMode.OnCell, Danger.Deadly)) { return(new Job(JobDefOf.ChJAndroidRecharge, closestPowerSource)); } //Check surrounding cells. foreach (IntVec3 adjCell in GenAdj.CellsAdjacentCardinal(building).OrderByDescending(selector => selector.DistanceTo(pawn.Position))) { if (adjCell.Walkable(pawn.Map) && adjCell.InAllowedArea(pawn) && pawn.CanReserve(new LocalTargetInfo(adjCell)) && pawn.CanReach(adjCell, PathEndMode.OnCell, Danger.Deadly)) { return(new Job(JobDefOf.ChJAndroidRecharge, closestPowerSource, adjCell)); } } } } //No power source? Try looking for a consumable resource. //In the inventory. (Or being carried) if (pawn.carryTracker is Pawn_CarryTracker carryTracker && carryTracker.CarriedThing is Thing carriedThing && carriedThing.TryGetComp <EnergySourceComp>() is EnergySourceComp carriedThingComp && carriedThingComp.EnergyProps.isConsumable) { if (carriedThing.stackCount > 0) { return(new Job(JobDefOf.ChJAndroidRechargeEnergyComp, new LocalTargetInfo(carriedThing)) { count = carriedThing.stackCount }); } } if (pawn.inventory is Pawn_InventoryTracker inventory && inventory.innerContainer.Any(thing => thing.TryGetComp <EnergySourceComp>() is EnergySourceComp comp && comp.EnergyProps.isConsumable)) { Thing validEnergySource = inventory.innerContainer.FirstOrDefault( thing => thing.TryGetComp <EnergySourceComp>() is EnergySourceComp energySource && energySource.EnergyProps.isConsumable ); if (validEnergySource != null) { //Use enough to get satisfied. EnergySourceComp energySourceComp = validEnergySource.TryGetComp <EnergySourceComp>(); int thingCount = (int)Math.Ceiling((energy.MaxLevel - energy.CurLevel) / energySourceComp.EnergyProps.energyWhenConsumed); thingCount = Math.Min(thingCount, validEnergySource.stackCount); if (thingCount > 0) { return(new Job(JobDefOf.ChJAndroidRechargeEnergyComp, new LocalTargetInfo(validEnergySource)) { count = thingCount }); } } } //On the map. Thing closestConsumablePowerSource = GenClosest.ClosestThingReachable( pawn.Position, pawn.Map, ThingRequest.ForGroup(ThingRequestGroup.HaulableEver), PathEndMode.OnCell, TraverseParms.For(pawn), 9999f, thing => thing.TryGetComp <EnergySourceComp>() != null && !thing.IsForbidden(pawn) && pawn.CanReserve(new LocalTargetInfo(thing)) && thing.Position.InAllowedArea(pawn) && pawn.CanReach(new LocalTargetInfo(thing), PathEndMode.OnCell, Danger.Deadly)); if (closestConsumablePowerSource != null) { EnergySourceComp energySourceComp = closestConsumablePowerSource.TryGetComp <EnergySourceComp>(); if (energySourceComp != null) { int thingCount = (int)Math.Ceiling((energy.MaxLevel - energy.CurLevel) / energySourceComp.EnergyProps.energyWhenConsumed); if (thingCount > 0) { return(new Job(JobDefOf.ChJAndroidRechargeEnergyComp, new LocalTargetInfo(closestConsumablePowerSource)) { count = thingCount }); } } } return(null); }
protected override IEnumerable<Toil> MakeNewToils() { yield return Toils_Reserve.Reserve(terraformerIndex); yield return Toils_Goto.GotoCell(terraformerIndex, PathEndMode.InteractionCell).FailOnDestroyed(terraformerIndex); yield return Toils_General.Wait(240).FailOnDestroyed(terraformerIndex); Toil scytherScoutsArrivalToil = new Toil() { initAction = () => { IntVec3 spawningCell; List<Pawn> scytherScoutsList = new List<Pawn>(); for (int scytherIndex = 0; scytherIndex < 4; scytherIndex++) { bool validDropPodCellIsFound = DropCellFinder.TryFindDropSpotNear(this.TargetThingA.InteractionCell, out spawningCell, true, true); if (validDropPodCellIsFound) { Faction faction = Faction.OfMechanoids; Pawn scytherScout = PawnGenerator.GeneratePawn(PawnKindDef.Named("Scyther"), faction); scytherScoutsList.Add(scytherScout); DropPodUtility.MakeDropPodAt(spawningCell, new DropPodInfo { SingleContainedThing = scytherScout, openDelay = 600, leaveSlag = false }); } } StateGraph stateGraph = GraphMaker.MechanoidsDefendShipGraph(this.TargetThingA, defensiveRadiusAroundTerraformer); BrainMaker.MakeNewBrain(Faction.OfMechanoids, stateGraph, scytherScoutsList); }, defaultCompleteMode = ToilCompleteMode.Instant }; yield return scytherScoutsArrivalToil; Toil pawnEscapingToil = new Toil() { initAction = () => { (this.TargetThingA as Building_MechanoidTerraformer).reverseEngineeringState = Building_MechanoidTerraformer.ReverseEngineeringState.BuildingNotSecured; ThingRequest thingRequest = new ThingRequest(); thingRequest.singleDef = ThingDefOf.CommsConsole; Thing commsConsole = GenClosest.ClosestThingReachable(pawn.Position, thingRequest, PathEndMode.InteractionCell, TraverseParms.For(pawn)); if (commsConsole != null) { pawn.pather.StartPath(commsConsole, PathEndMode.InteractionCell); } else { // The player has no comms console. He should move his colonist manually... and fast! pawn.pather.StartPath(pawn.Position, PathEndMode.OnCell); } string herHimOrIt = "it"; string sheHeOrIt = "it"; if (pawn.gender == Gender.Female) { herHimOrIt = "her"; sheHeOrIt = "she"; } else if (pawn.gender == Gender.Male) { herHimOrIt = "him"; sheHeOrIt = "he"; } string eventText = " " + pawn.Name.ToStringShort + " is just arriving near the strange building when " + sheHeOrIt + " hears the loud noise of incoming drop pods.\n\n" + "You should better take " + herHimOrIt + " to safety... and fast!\n"; Find.LetterStack.ReceiveLetter("Drop pods", eventText, LetterType.BadUrgent, this.pawn.Position); }, defaultCompleteMode = ToilCompleteMode.PatherArrival }; yield return pawnEscapingToil; yield return Toils_Reserve.Release(terraformerIndex); }