Esempio n. 1
0
 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);
            }
        }
Esempio n. 3
0
        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);
        }
Esempio n. 4
0
        // 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);
        }
Esempio n. 6
0
        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);
        }
Esempio n. 10
0
 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));
 }
Esempio n. 11
0
        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);
        }
Esempio n. 14
0
        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
            });
        }
Esempio n. 16
0
        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);
        }
Esempio n. 17
0
        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);
        }
Esempio n. 18
0
        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));
        }
Esempio n. 20
0
        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);
        }
Esempio n. 21
0
        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);
        }
Esempio n. 22
0
        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);
        }
Esempio n. 23
0
        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);
        }
Esempio n. 24
0
        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);
        }
Esempio n. 25
0
        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);
        }
Esempio n. 27
0
        // 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;
                }
            }
        }
Esempio n. 28
0
 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;
     }));
 }
Esempio n. 29
0
        // 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));
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
Esempio n. 30
0
        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);
        }