コード例 #1
0
        public static bool CanReach(this Reachability reachability, IntVec3 start, LocalTargetInfo dest, PathEndMode peMode, TraverseParms traverseParams)
        {
            // NOTE: not checking reachability.working
            if (traverseParams.thing != null)
            {
                if (!traverseParams.thing.Spawned)
                {
                    return(false);
                }
                // ERROR: thing.map != this.map
            }
            if (ReachabilityImmediate.CanReachImmediate(start, dest, reachability.GetMap(), peMode, traverseParams.thing))
            {
                return(true);
            }
            if (!dest.IsValid)
            {
                return(false);
            }
            if (dest.HasThing && dest.Thing.Map != reachability.GetMap())
            {
                return(false);
            }
            if (!start.InBounds(reachability.GetMap()) || !dest.Cell.InBounds(reachability.GetMap()))
            {
                return(false);
            }
            if (peMode == PathEndMode.OnCell || peMode == PathEndMode.Touch || peMode == PathEndMode.ClosestTouch)
            {
                Room room = RegionAndRoomQuery.RoomAtFast(start, reachability.GetMap(), RegionType.Set_Passable);
                if (room != null && room == RegionAndRoomQuery.RoomAtFast(dest.Cell, reachability.GetMap(), RegionType.Set_Passable))
                {
                    return(true);
                }
            }

            return(true); // TEMP
        }
コード例 #2
0
        public static bool CanReach(Reachability __instance, ref bool __result, IntVec3 start, LocalTargetInfo dest, PathEndMode peMode, TraverseParms traverseParams)
        {
            Map map = __instance.map;

            //if (working)
            //{
            //Log.ErrorOnce("Called CanReach() while working. This should never happen. Suppressing further errors.", 7312233);
            //return false;
            //}

            if (traverseParams.pawn != null)
            {
                if (!traverseParams.pawn.Spawned)
                {
                    __result = false;
                    return(false);
                }

                if (traverseParams.pawn.Map != map)
                {
                    Log.Error(string.Concat("Called CanReach() with a pawn spawned not on this map. This means that we can't check his reachability here. Pawn's current map should have been used instead of this one. pawn=", traverseParams.pawn, " pawn.Map=", traverseParams.pawn.Map, " map=", map));
                    __result = false;
                    return(false);
                }
            }

            if (ReachabilityImmediate.CanReachImmediate(start, dest, map, peMode, traverseParams.pawn))
            {
                __result = true;
                return(false);
            }

            if (!dest.IsValid)
            {
                __result = false;
                return(false);
            }

            if (dest.HasThing && dest.Thing.Map != map)
            {
                __result = false;
                return(false);
            }

            if (!start.InBounds(map) || !dest.Cell.InBounds(map))
            {
                __result = false;
                return(false);
            }

            if ((peMode == PathEndMode.OnCell || peMode == PathEndMode.Touch || peMode == PathEndMode.ClosestTouch) && traverseParams.mode != TraverseMode.NoPassClosedDoorsOrWater && traverseParams.mode != TraverseMode.PassAllDestroyableThingsNotWater)
            {
#if RW12
                Room room = RegionAndRoomQuery.RoomAtFast(start, map);
                if (room != null && room == RegionAndRoomQuery.RoomAtFast(dest.Cell, map))
#endif
#if RW13
                District district = RegionAndRoomQuery.DistirctAtFast(start, map);
                if (district != null && district == RegionAndRoomQuery.DistirctAtFast(dest.Cell, map))
#endif
                {
                    __result = true;
                    return(false);
                }
            }

            if (traverseParams.mode == TraverseMode.PassAllDestroyableThings)
            {
                TraverseParms traverseParams2 = traverseParams;
                traverseParams2.mode = TraverseMode.PassDoors;
                bool canReachResult = false;
                CanReach(__instance, ref canReachResult, start, dest, peMode, traverseParams2);
                if (canReachResult)
                {
                    __result = true;
                    return(false);
                }
            }

            dest = (LocalTargetInfo)GenPath.ResolvePathMode(traverseParams.pawn, dest.ToTargetInfo(map), ref peMode);
            //working = true;
            try
            {
#if RW12
                __instance.pathGrid = map.pathGrid;
                PathGrid pathGrid = map.pathGrid;
#endif
#if RW13
                __instance.pathGrid = map.pathing.For(traverseParams).pathGrid;
                PathGrid pathGrid = __instance.pathGrid;
#endif
                __instance.regionGrid = map.regionGrid;
                RegionGrid regionGrid = map.regionGrid;

                destRegions.Clear();

                switch (peMode)
                {
                case PathEndMode.OnCell:
                {
                    Region region = dest.Cell.GetRegion(map);
                    if (region != null && region.Allows(traverseParams, isDestination: true))
                    {
                        destRegions.Add(region);
                    }
                    break;
                }

                case PathEndMode.Touch:
                    TouchPathEndModeUtility.AddAllowedAdjacentRegions(dest, traverseParams, map, destRegions);
                    break;
                }

                if (destRegions.Count == 0 && traverseParams.mode != TraverseMode.PassAllDestroyableThings && traverseParams.mode != TraverseMode.PassAllDestroyableThingsNotWater)
                {
                    __result = false;
                    return(false);
                }

                destRegions.RemoveDuplicates();
                regionsReached.Clear();
                openQueue.Clear();
                startingRegions.Clear();

                DetermineStartRegions(map, start, startingRegions, pathGrid, regionGrid, openQueue, regionsReached);
                if (openQueue.Count == 0 && traverseParams.mode != TraverseMode.PassAllDestroyableThings && traverseParams.mode != TraverseMode.PassAllDestroyableThingsNotWater)
                {
                    __result = false;
                    return(false);
                }

                if (startingRegions.Any() && destRegions.Any() && __instance.CanUseCache(traverseParams.mode))
                {
                    switch (GetCachedResult(__instance, traverseParams, startingRegions, destRegions))
                    {
                    case BoolUnknown.True:
                        __result = true;
                        return(false);

                    case BoolUnknown.False:
                        __result = false;
                        return(false);
                    }
                }
                if (traverseParams.mode == TraverseMode.PassAllDestroyableThings || traverseParams.mode == TraverseMode.PassAllDestroyableThingsNotWater || traverseParams.mode == TraverseMode.NoPassClosedDoorsOrWater)
                {
                    bool result = __instance.CheckCellBasedReachability(start, dest, peMode, traverseParams);
                    __result = result;
                    return(false);
                }

                bool result2 = CheckRegionBasedReachability(__instance, traverseParams, openQueue, regionsReached, startingRegions, destRegions);
                __result = result2;
                return(false);
            }
            finally
            {
                //working = false;
            }
        }
コード例 #3
0
        protected override Job TryGiveJob(Pawn pawn)
        {
            if (!Controller.settings.EnableAmmoSystem || !Controller.settings.AutoTakeAmmo)
            {
                return(null);
            }

            if (!pawn.RaceProps.Humanlike || (pawn.story != null && pawn.story.WorkTagIsDisabled(WorkTags.Violent)))
            {
                return(null);
            }
            if (pawn.Faction.IsPlayer && pawn.Drafted)
            {
                return(null);
            }

            if (!Rand.MTBEventOccurs(60, 1, 30))
            {
                return(null);
            }

            // Log.Message(pawn.ToString() +  " - 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;

            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);
                        }
                    }
                }

                // Drop excess ranged weapon
                if (!pawn.Faction.IsPlayer && primaryammouser != null && GetPriorityWork(pawn) == 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(new Job(JobDefOf.DropEquipment, droppedWeapon, 30, true));
                            }
                        }
                    }
                }

                // Find and drop not need ammo from inventory
                if (!pawn.Faction.IsPlayer && hasPrimary && inventory.ammoList.Count > 1 && GetPriorityWork(pawn) == 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(new Job(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(new Job(JobDefOf.DropEquipment, 30, true));
                            }
                        }
                    }
                }

                Room room = RegionAndRoomQuery.RoomAtFast(pawn.Position, pawn.Map);

                // Find weapon in inventory and try to switch if any ammo in inventory.
                if (GetPriorityWork(pawn) == 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) &&
                                                        (DangerInPosRadius(pawn, w.Position, pawn.Map, 30f).Count() <= 0
                                                    ? pawn.Position.InHorDistOf(w.Position, 25f)
                                                    : pawn.Position.InHorDistOf(w.Position, 6f)) &&
                                                        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(new Job(JobDefOf.Equip, thing)
                                        {
                                            checkOverrideOnExpire = true,
                                            expiryInterval = 100
                                        });
                                    }
                                }
                                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) &&
                                                                   (DangerInPosRadius(pawn, t.Position, pawn.Map, 30f).Count() <= 0
                                                                ? pawn.Position.InHorDistOf(t.Position, 25f)
                                                                : pawn.Position.InHorDistOf(t.Position, 6f)) &&
                                                                   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(new Job(JobDefOf.Equip, thing)
                                                {
                                                    checkOverrideOnExpire = true,
                                                    expiryInterval = 100
                                                });
                                            }
                                        }
                                    }
                                }
                            }
                        }

                        // 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(new Job(JobDefOf.Equip, meleeWeapon)
                                {
                                    checkOverrideOnExpire = true,
                                    expiryInterval = 100
                                });
                            }
                        }
                    }
                }

                // Find ammo
                if ((GetPriorityWork(pawn) == WorkPriority.Ammo || GetPriorityWork(pawn) == WorkPriority.LowAmmo) &&
                    primaryammouser != null)
                {
                    List <ThingDef> curAmmoList = (from AmmoLink g in primaryammouser.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 && DangerInPosRadius(pawn, t.Position, Find.VisibleMap, 30f).Count() <= 0
                                                                ? pawn.Position.InHorDistOf(t.Position, 25f)
                                                                : pawn.Position.InHorDistOf(t.Position, 6f))) &&
                                                      (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 (GetPriorityWork(pawn) == 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))
                                                {
                                                    return(new Job(JobDefOf.TakeInventory, th)
                                                    {
                                                        count = numToCarry
                                                    });
                                                }
                                            }
                                        }
                                        else
                                        {
                                            int numToCarry = 0;
                                            if (inventory.CanFitInInventory(th, out numToCarry))
                                            {
                                                return(new Job(JobDefOf.TakeInventory, th)
                                                {
                                                    count = Mathf.RoundToInt(numToCarry * 0.8f),
                                                    expiryInterval = 150,
                                                    checkOverrideOnExpire = true
                                                });
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    }
                }

                /*
                 * if (!pawn.Faction.IsPlayer && pawn.apparel != null && GetPriorityWork(pawn) == 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 new Job(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 new Job(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 new Job(JobDefOf.Wear, apparel3)
                 *              {
                 *                  ignoreForbidden = true,
                 *                  locomotionUrgency = LocomotionUrgency.Sprint
                 *              };
                 *          }
                 *      }
                 *  }
                 * }
                 */
                return(null);
            }
            return(null);
        }
コード例 #4
0
        public bool CanReach(IntVec3 start, LocalTargetInfo dest, PathEndMode peMode, TraverseParms traverseParams)
        {
            if (this.working)
            {
                Log.ErrorOnce("Called ReachableBetween while working. This should never happen. Suppressing further errors.", 7312233);
                return(false);
            }
            if (traverseParams.pawn != null)
            {
                if (!traverseParams.pawn.Spawned)
                {
                    return(false);
                }
                if (traverseParams.pawn.Map != this.map)
                {
                    Log.Error(string.Concat(new object[]
                    {
                        "Called CanReach() with a pawn spawned not on this map. This means that we can't check his reachability here. Pawn's current map should have been used instead of this one. pawn=",
                        traverseParams.pawn,
                        " pawn.Map=",
                        traverseParams.pawn.Map,
                        " map=",
                        this.map
                    }));
                    return(false);
                }
            }
            if (ReachabilityImmediate.CanReachImmediate(start, dest, this.map, peMode, traverseParams.pawn))
            {
                return(true);
            }
            if (!dest.IsValid)
            {
                return(false);
            }
            if (dest.HasThing && dest.Thing.Map != this.map)
            {
                return(false);
            }
            if (!start.InBounds(this.map) || !dest.Cell.InBounds(this.map))
            {
                return(false);
            }
            if (peMode == PathEndMode.OnCell || peMode == PathEndMode.Touch || peMode == PathEndMode.ClosestTouch)
            {
                Room room = RegionAndRoomQuery.RoomAtFast(start, this.map, RegionType.Set_Passable);
                if (room != null && room == RegionAndRoomQuery.RoomAtFast(dest.Cell, this.map, RegionType.Set_Passable))
                {
                    return(true);
                }
            }
            if (traverseParams.mode == TraverseMode.PassAllDestroyableThings)
            {
                TraverseParms traverseParams2 = traverseParams;
                traverseParams2.mode = TraverseMode.PassDoors;
                if (this.CanReach(start, dest, peMode, traverseParams2))
                {
                    return(true);
                }
            }
            dest         = (LocalTargetInfo)GenPath.ResolvePathMode(traverseParams.pawn, dest.ToTargetInfo(this.map), ref peMode);
            this.working = true;
            bool result;

            try
            {
                this.pathGrid      = this.map.pathGrid;
                this.regionGrid    = this.map.regionGrid;
                this.reachedIndex += 1u;
                this.destRegions.Clear();
                if (peMode == PathEndMode.OnCell)
                {
                    Region region = dest.Cell.GetRegion(this.map, RegionType.Set_Passable);
                    if (region != null && region.Allows(traverseParams, true))
                    {
                        this.destRegions.Add(region);
                    }
                }
                else if (peMode == PathEndMode.Touch)
                {
                    TouchPathEndModeUtility.AddAllowedAdjacentRegions(dest, traverseParams, this.map, this.destRegions);
                }
                if (this.destRegions.Count == 0 && traverseParams.mode != TraverseMode.PassAllDestroyableThings)
                {
                    this.FinalizeCheck();
                    result = false;
                }
                else
                {
                    this.destRegions.RemoveDuplicates <Region>();
                    this.openQueue.Clear();
                    this.numRegionsOpened = 0;
                    this.DetermineStartRegions(start);
                    if (this.openQueue.Count == 0 && traverseParams.mode != TraverseMode.PassAllDestroyableThings)
                    {
                        this.FinalizeCheck();
                        result = false;
                    }
                    else
                    {
                        if (this.startingRegions.Any <Region>() && this.destRegions.Any <Region>())
                        {
                            BoolUnknown cachedResult = this.GetCachedResult(traverseParams);
                            if (cachedResult == BoolUnknown.True)
                            {
                                this.FinalizeCheck();
                                result = true;
                                return(result);
                            }
                            if (cachedResult == BoolUnknown.False)
                            {
                                this.FinalizeCheck();
                                result = false;
                                return(result);
                            }
                            if (cachedResult != BoolUnknown.Unknown)
                            {
                            }
                        }
                        if (traverseParams.mode == TraverseMode.PassAllDestroyableThings)
                        {
                            bool flag = this.CheckCellBasedReachability(start, dest, peMode, traverseParams);
                            this.FinalizeCheck();
                            result = flag;
                        }
                        else
                        {
                            bool flag2 = this.CheckRegionBasedReachability(traverseParams);
                            this.FinalizeCheck();
                            result = flag2;
                        }
                    }
                }
            }
            finally
            {
                this.working = false;
            }
            return(result);
        }
コード例 #5
0
        static Job FindBedrollJob(Job fallbackJob, Pawn pawn)
        {
            if (!pawn.IsColonistPlayerControlled)
            {
                return(fallbackJob);
            }
            Log.Message(pawn + " looking for inventory beds");

            MinifiedThing invBed = (MinifiedThing)FindMinifiedBed(pawn);

            if (invBed == null)
            {
                return(fallbackJob);
            }
            Log.Message(pawn + " found " + invBed);

            Map          map = pawn.Map;
            Building_Bed bed = (Building_Bed)invBed.GetInnerIfMinified();

            Func <IntVec3, Rot4, bool> cellValidatorDir = delegate(IntVec3 c, Rot4 direction)
            {
                if (RegionAndRoomQuery.RoomAtFast(c, map).isPrisonCell != pawn.IsPrisoner)
                {
                    return(false);
                }

                if (!GenConstruct.CanPlaceBlueprintAt(invBed.GetInnerIfMinified().def, c, direction, map).Accepted)
                {
                    return(false);
                }

                if (c.IsForbidden(pawn))
                {
                    return(false);
                }

                for (CellRect.CellRectIterator iterator = GenAdj.OccupiedRect(c, direction, bed.def.size).GetIterator();
                     !iterator.Done(); iterator.MoveNext())
                {
                    foreach (Thing t in iterator.Current.GetThingList(map))
                    {
                        if (!(t is Pawn) && GenConstruct.BlocksConstruction(bed, t))
                        {
                            return(false);
                        }
                    }
                    if (!(map.zoneManager.ZoneAt(c) is null))
                    {
                        return(false);
                    }
                }

                return(true);
            };

            // North/East would be redundant, except for cells on edge ; oh well, too much code to handle that
            Predicate <IntVec3> cellValidator = c => cellValidatorDir(c, Rot4.South) || cellValidatorDir(c, Rot4.West);

            Predicate <IntVec3> goodCellValidator = c =>
                                                    !RegionAndRoomQuery.RoomAt(c, map).PsychologicallyOutdoors&& cellValidator(c);

            IntVec3       placePosition = IntVec3.Invalid;
            IntVec3       root          = pawn.Position;
            TraverseParms trav          = TraverseParms.For(pawn);

            if (!CellFinder.TryFindRandomReachableCellNear(root, map, 4, trav, goodCellValidator, null, out placePosition))
            {
                if (!CellFinder.TryFindRandomReachableCellNear(root, map, 12, trav, goodCellValidator, null, out placePosition))
                {
                    if (!CellFinder.TryFindRandomReachableCellNear(root, map, 4, trav, cellValidator, null, out placePosition))
                    {
                        CellFinder.TryFindRandomReachableCellNear(root, map, 12, trav, cellValidator, null, out placePosition);
                    }
                }
            }

            if (placePosition.IsValid)
            {
                Rot4 dir = cellValidatorDir(placePosition, Rot4.South) ? Rot4.South : Rot4.West;
                Blueprint_Install blueprint = GenConstruct.PlaceBlueprintForInstall(invBed, placePosition, map, dir, pawn.Faction);

                Log.Message(pawn + " placing " + blueprint + " at " + placePosition);

                return(new Job(JobDefOf.PlaceBedroll, invBed, blueprint)
                {
                    haulMode = HaulMode.ToContainer
                });
            }
            Log.Message(pawn + " couldn't find place for " + invBed);

            return(fallbackJob);
        }
コード例 #6
0
ファイル: Reachability.cs プロジェクト: xywf221/RimThreaded
        public static bool CanReach(Reachability __instance, ref bool __result,
                                    IntVec3 start,
                                    LocalTargetInfo dest,
                                    PathEndMode peMode,
                                    TraverseParms traverseParams)
        {
            /*
             * if (working)
             * {
             *  Log.ErrorOnce("Called CanReach() while working. This should never happen. Suppressing further errors.", 7312233);
             *  return false;
             * }
             */

            Map this_map = map(__instance);

            if (traverseParams.pawn != null)
            {
                if (!traverseParams.pawn.Spawned)
                {
                    __result = false;
                    return(false);
                }
                if (traverseParams.pawn.Map != this_map)
                {
                    Log.Error("Called CanReach() with a pawn spawned not on this map. This means that we can't check his reachability here. Pawn's current map should have been used instead of this one. pawn=" +
                              (object)traverseParams.pawn + " pawn.Map=" + (object)traverseParams.pawn.Map + " map=" + (object)map(__instance), false);
                    __result = false;
                    return(false);
                }
            }
            if (ReachabilityImmediate.CanReachImmediate(start, dest, this_map, peMode, traverseParams.pawn))
            {
                __result = true;
                return(false);
            }
            if (!dest.IsValid || dest.HasThing && dest.Thing.Map != this_map || (!start.InBounds(this_map) || !dest.Cell.InBounds(this_map)))
            {
                __result = false;
                return(false);
            }
            if ((peMode == PathEndMode.OnCell || peMode == PathEndMode.Touch || peMode == PathEndMode.ClosestTouch) && (traverseParams.mode != TraverseMode.NoPassClosedDoorsOrWater && traverseParams.mode != TraverseMode.PassAllDestroyableThingsNotWater))
            {
                Room room = RegionAndRoomQuery.RoomAtFast(start, this_map, RegionType.Set_Passable);
                if (room != null && room == RegionAndRoomQuery.RoomAtFast(dest.Cell, this_map, RegionType.Set_Passable))
                {
                    __result = true;
                    return(false);
                }
            }
            if (traverseParams.mode == TraverseMode.PassAllDestroyableThings)
            {
                TraverseParms traverseParams1 = traverseParams;
                traverseParams1.mode = TraverseMode.PassDoors;
                if (__instance.CanReach(start, dest, peMode, traverseParams1))
                {
                    __result = true;
                    return(false);
                }
            }
            dest = (LocalTargetInfo)GenPath.ResolvePathMode(traverseParams.pawn, dest.ToTargetInfo(this_map), ref peMode);
            //working = true;
            try
            {
                uint this_reachedIndex;                                   //Replaced reachedIndex
                lock (reachedIndexLock)                                   //Added
                {
                    this_reachedIndex   = offsetReachedIndex;             //Added
                    offsetReachedIndex += 100000;                         //Added
                }
                HashSet <Region> regionsReached = new HashSet <Region>(); //Added
                PathGrid         pathGrid       = this_map.pathGrid;      //Replaced pathGrid
                RegionGrid       regionGrid     = this_map.regionGrid;    //Replaced regionGrid
                ++this_reachedIndex;                                      //Replaced reachedIndex

                //this_destRegions.Clear();
                List <Region> this_destRegions = new List <Region>(); //Replaced destRegions
                switch (peMode)
                {
                case PathEndMode.OnCell:
                    Region region = dest.Cell.GetRegion(this_map, RegionType.Set_Passable);
                    if (region != null && region.Allows(traverseParams, true))
                    {
                        this_destRegions.Add(region);
                        break;
                    }
                    break;

                case PathEndMode.Touch:
                    TouchPathEndModeUtility.AddAllowedAdjacentRegions(dest, traverseParams, this_map, this_destRegions);
                    break;
                }
                if (this_destRegions.Count == 0 && traverseParams.mode != TraverseMode.PassAllDestroyableThings && traverseParams.mode != TraverseMode.PassAllDestroyableThingsNotWater)
                {
                    //this.FinalizeCheck();
                    __result = false;
                    return(false);
                }
                this_destRegions.RemoveDuplicates <Region>();
                //this_openQueue.Clear();
                Queue <Region> this_openQueue        = new Queue <Region>(); //Replaced openQueue
                int            this_numRegionsOpened = 0;                    //Replaced numRegionsOpened
                List <Region>  this_startingRegions  = new List <Region>();
                DetermineStartRegions2(__instance, start, this_startingRegions, pathGrid, regionGrid, this_reachedIndex, this_openQueue, ref this_numRegionsOpened, regionsReached);
                if (this_openQueue.Count == 0 && traverseParams.mode != TraverseMode.PassAllDestroyableThings && traverseParams.mode != TraverseMode.PassAllDestroyableThingsNotWater)
                {
                    //this.FinalizeCheck();
                    __result = false;
                    return(false);
                }
                ReachabilityCache this_cache = cache(__instance);
                if (this_startingRegions.Any <Region>() && this_destRegions.Any <Region>() && CanUseCache(traverseParams.mode))
                {
                    switch (GetCachedResult2(traverseParams, this_startingRegions, this_destRegions, this_cache))
                    {
                    case BoolUnknown.True:
                        //this.FinalizeCheck();
                        __result = true;
                        return(false);

                    case BoolUnknown.False:
                        //this.FinalizeCheck();
                        __result = false;
                        return(false);
                    }
                }
                if (traverseParams.mode == TraverseMode.PassAllDestroyableThings || traverseParams.mode == TraverseMode.PassAllDestroyableThingsNotWater || traverseParams.mode == TraverseMode.NoPassClosedDoorsOrWater)
                {
                    int num = CheckCellBasedReachability(start, dest, peMode, traverseParams,
                                                         regionGrid, __instance, this_startingRegions, this_cache, this_destRegions
                                                         ) ? 1 : 0;
                    //this.FinalizeCheck();
                    __result = num != 0;
                    return(false);
                }
                int num1 = CheckRegionBasedReachability(traverseParams,
                                                        this_openQueue, this_reachedIndex,
                                                        this_destRegions, this_startingRegions, this_cache, ref this_numRegionsOpened, regionsReached
                                                        ) ? 1 : 0;
                //this.FinalizeCheck();
                __result = num1 != 0;
                return(false);
            }
            finally
            {
            }
        }