public static bool TryFindBestBetterStorageFor(Thing t, Pawn carrier, Map map, StoragePriority currentPriority, Faction faction, out IntVec3 foundCell, out IHaulDestination haulDestination, bool needAccurateResult = true)
        {
            IntVec3         invalid         = IntVec3.Invalid;
            StoragePriority storagePriority = StoragePriority.Unstored;

            if (StoreUtility.TryFindBestBetterStoreCellFor(t, carrier, map, currentPriority, faction, out invalid, needAccurateResult))
            {
                storagePriority = invalid.GetSlotGroup(map).Settings.Priority;
            }
            IHaulDestination haulDestination2;

            if (!StoreUtility.TryFindBestBetterNonSlotGroupStorageFor(t, carrier, map, currentPriority, faction, out haulDestination2))
            {
                haulDestination2 = null;
            }
            if (storagePriority == StoragePriority.Unstored && haulDestination2 == null)
            {
                foundCell       = IntVec3.Invalid;
                haulDestination = null;
                return(false);
            }
            if (haulDestination2 != null && (storagePriority == StoragePriority.Unstored || haulDestination2.GetStoreSettings().Priority > storagePriority))
            {
                foundCell       = IntVec3.Invalid;
                haulDestination = haulDestination2;
                return(true);
            }
            foundCell       = invalid;
            haulDestination = invalid.GetSlotGroup(map).parent;
            return(true);
        }
        public static void FilledEnough(ref bool __result, IntVec3 c, Map map, Thing thing)
        {
            // if base implementation waves of, then don't need to care
            if (__result)
            {
                float num  = 100f;
                bool  flag = c.GetSlotGroup(map) != null && c.GetSlotGroup(map).Settings != null;
                if (flag)
                {
                    num = StorageSettings_Mapping.Get(c.GetSlotGroup(map).Settings).FillPercent;
                }

                __result &= !map.thingGrid.ThingsListAt(c).Any(t => t.def.EverStorable(false) && t.stackCount >= thing.def.stackLimit * (num / 100f));
            }
        }
        // credit to bananasss00 for this function
        public static bool TryGetKanbanSettings(this IntVec3 cell, Map map, out KanbanSettings ks, out SlotGroup slotGroup)
        {
            ks        = new KanbanSettings();
            slotGroup = null;

            if (map == null)
            {
                return(false);
            }

            slotGroup = cell.GetSlotGroup(map);
            if (slotGroup?.Settings == null)
            {
                return(false);
            }

            // grab latest configs for this stockpile from our state manager
            ks = State.Get(slotGroup.Settings.owner.ToString());

            // skip all this stuff now if stockpile is not configured to use at least one feature
            if (ks.srt == 100 && ks.ssl == 0)
            {
                return(false);
            }

            return(true);
        }
Beispiel #4
0
        static bool Prefix(ref float __result, IntVec3 c, Map map, List <Thing> countedThings = null)
        {
            SlotGroup slotgroup = c.GetSlotGroup(map);

            if (slotgroup == null)
            {
                return(true);
            }
            if (!(slotgroup.parent is Building_Storage))
            {
                return(true);
            }
            if (!slotgroup.parent.IgnoreStoredThingsBeauty)
            {
                return(true);
            }
            Building_Storage storage = slotgroup.parent as Building_Storage;

            if (countedThings != null)
            {
                // Ignoring all the other things here because that's best:
                // What if a pretty rug were here, but also a shelf?  Suddenly,
                // no beauty from the rug, but also no counting its beauty
                // elsewhere in the room!
                if (countedThings.Contains(storage))
                {
                    __result = map.terrainGrid.TerrainAt(c).GetStatValueAbstract(StatDefOf.Beauty, null);
                    return(false);
                }
                countedThings.Add(storage);
            }
            __result = storage.GetStatValue(StatDefOf.Beauty, true) +
                       map.terrainGrid.TerrainAt(c).GetStatValueAbstract(StatDefOf.Beauty, null);
            return(false);
        }
Beispiel #5
0
        public override string GetReport()
        {
            ThingWithComps cart = TargetThingA as ThingWithComps;

            IntVec3   destLoc   = new IntVec3(-1000, -1000, -1000);
            string    destName  = null;
            SlotGroup destGroup = null;


            if (pawn.jobs.curJob.targetB != null)
            {
                destLoc   = pawn.jobs.curJob.targetB.Cell;
                destGroup = destLoc.GetSlotGroup();
            }

            if (destGroup != null)
            {
                destName = destGroup.parent.SlotYielderLabel();
            }

            string repString;

            if (destName != null)
            {
                repString = "ReportDismountingOn".Translate(cart.LabelCap, destName);
            }
            else
            {
                repString = "ReportDismounting".Translate(cart.LabelCap);
            }

            return(repString);
        }
Beispiel #6
0
        public override string GetReport()
        {
            IntVec3 cell  = job.targetB.Cell;
            Thing   thing = null;

            if (pawn.CurJob == job && pawn.carryTracker.CarriedThing != null)
            {
                thing = pawn.carryTracker.CarriedThing;
            }
            else if (base.TargetThingA != null && base.TargetThingA.Spawned)
            {
                thing = base.TargetThingA;
            }
            if (thing == null)
            {
                return("ReportHaulingUnknown".Translate());
            }
            string    text      = null;
            SlotGroup slotGroup = cell.GetSlotGroup(base.Map);

            if (slotGroup != null)
            {
                text = slotGroup.parent.SlotYielderLabel();
            }
            if (text != null)
            {
                return("ReportHaulingTo".Translate(thing.Label, text.Named("DESTINATION"), thing.Named("THING")));
            }
            return("ReportHauling".Translate(thing.Label, thing));
        }
        // This gets checked a lot.  Sometimes the test is done in-place (if will 
        //   need to use the slotGroup later, for example), but when using Harmony 
        //   Transpiler, tests are easier via function call
        // Most of the bulk here is debugging stuff
        public static bool CanStoreMoreThanOneThingAt(Map map, IntVec3 loc)
        {
            var slotGroup = loc.GetSlotGroup(map);
            if (slotGroup == null || !(slotGroup?.parent is ThingWithComps) ||
                (slotGroup.parent as ThingWithComps).TryGetComp<CompDeepStorage>() == null)
            {
                return false;
#pragma warning disable CS0162 // Unreachable code detected
                Log.Warning("CanStoreMoreThanOneThingAt: " + loc + "? false");
                return false;
                if (slotGroup == null) Log.Warning("  null slotGroup");
                else if (slotGroup.parent == null) Log.Warning("  null slotGroup.parent");
                else if (!(slotGroup.parent is ThingWithComps)) Log.Warning("  slotGroup.parent is not ThingWithComps");
                else Log.Warning("  no CompDeepStorage");
                Log.Warning("Just for the record, " + (Scribe.mode == LoadSaveMode.LoadingVars) +
                            (Scribe.mode == LoadSaveMode.PostLoadInit) +
                            Scribe.mode);
                var l = map.thingGrid.ThingsListAt(loc);
                foreach (var t in l) Log.Error("Did find a " + t + " here at " + loc);
                return false;
            }

            //            Log.Warning("CanStoreMoreThanOneThingAt: " + loc.ToString() + "? true");
            return true;
            Log.Warning("CanStoreMoreThanOneThingAt: " + loc + "? true!");
            var lx = map.thingGrid.ThingsListAt(loc);
            foreach (var t in lx) Log.Error("Did find a " + t + " here at " + loc);
            return true;
#pragma warning restore CS0162 // Unreachable code detected
        }
        public static bool IsValidStorageFor(this IntVec3 c, Map map, Thing storable)
        {
            if (!StoreUtility.NoStorageBlockersIn(c, map, storable))
            {
                return(false);
            }
            SlotGroup slotGroup = c.GetSlotGroup(map);

            return(slotGroup != null && slotGroup.parent.Accepts(storable));
        }
        // duplicated to make changes
        public bool IsValidStorageFor(IntVec3 c, Thing storable)
        {
            // call duplicated to make changes
            if (!WorkGiver_HaulGeneral.NoStorageBlockersIn(c, storable))
            {
                return(false);
            }
            SlotGroup slotGroup = c.GetSlotGroup();

            return(slotGroup != null && slotGroup.Settings.AllowedToAccept(storable));
        }
        public static List <Thing> ThingListToDisplay(Map map, IntVec3 loc)
        {
            CompDeepStorage cds;
            var             slotGroup = loc.GetSlotGroup(map);

            if (!(slotGroup?.parent is ThingWithComps) || (cds = (slotGroup.parent as ThingWithComps).TryGetComp <CompDeepStorage>()) == null || cds.showContents)
            {
                return(map.thingGrid.ThingsListAt(loc));
            }
            // only return non-storable things to be drawn:
            return(map.thingGrid.ThingsListAt(loc).FindAll(t => !t.def.EverStorable(false)));
        }
Beispiel #11
0
        public static bool Postfix(bool result, IntVec3 c, Map map, Thing thing)
        {
            if (result == false)
            {
                return(result);
            }
            var slotgroup = c.GetSlotGroup(map);

            if (slotgroup == null)
            {
                return(result);
            }
            var setting       = slotgroup.Settings;
            var limit         = setting.GetStacklimit();
            var refillpercent = setting.GetRefillPercent();

            if (setting.IsRefillingDisabled() || limit == 0)
            {
                return(false);
            }
            if (limit < 0)
            {
                if (refillpercent == 100)
                {
                    return(result);
                }
                limit = thing.def.stackLimit;
            }
            limit *= refillpercent;
            foreach (var thing2 in map.thingGrid.ThingsListAt(c))
            {
                if (thing2.def.EverStorable(false))
                {
                    if (!thing2.CanStackWith(thing))
                    {
                        return(false);
                    }
                    if (thing2.stackCount * 100 >= limit)
                    {
                        return(false);
                    }
                }
                if (thing2.def.entityDefToBuild != null && thing2.def.entityDefToBuild.passability != Traversability.Standable)
                {
                    return(false);
                }
                if (thing2.def.surfaceType == SurfaceType.None && thing2.def.passability != Traversability.Standable)
                {
                    return(false);
                }
            }
            return(true);
        }
Beispiel #12
0
        public static bool IsValidStorageFor(this IntVec3 c, Map map, Thing storable)
        {
            if (!NoStorageBlockersIn(c, map, storable))
            {
                return(false);
            }
            SlotGroup slotGroup = c.GetSlotGroup(map);

            if (slotGroup == null || !slotGroup.parent.Accepts(storable))
            {
                return(false);
            }
            return(true);
        }
Beispiel #13
0
        public static bool IsValidStorageFor(this IntVec3 c, Map map, Thing storable)
        {
            if (!StoreUtility.NoStorageBlockersIn(c, map, storable))
            {
                return(false);
            }
            SlotGroup slotGroup = c.GetSlotGroup(map);

            if (slotGroup != null && slotGroup.Settings.AllowedToAccept(storable))
            {
                return(true);
            }
            return(false);
        }
        public static bool TryGetHaulingDestination(this Job job, out Map map, out IntVec3 dest, out SlotGroup slotGroup)
        {
            map       = null;
            slotGroup = null;
            dest      = new IntVec3();

            // Could print warnings here, hopefully these don't fail silently
            if (job == null)
            {
                return(false);
            }

            if (job.def == JobDefOf.HaulToContainer)
            {
                Thing container = job.targetB.Thing;
                if (container == null)
                {
                    return(false);
                }
                map  = container.Map;
                dest = container.Position;
            }
            else
            {
                // case JobDefOf.HaulToCell
                dest = job.targetB.Cell;
                map  = job.targetA.Thing.Map ?? job.targetA.Thing.MapHeld;
            }

            if (map == null)
            {
                return(false);
            }
            if (dest == null)
            {
                return(false);
            }

            slotGroup = dest.GetSlotGroup(map);
            if (slotGroup == null)
            {
                return(false);
            }

            return(true);
        }
Beispiel #15
0
 public static void ReplimatHopperFilledEnough(ref bool __result, IntVec3 c, Map map, Thing thing)
 {
     if (__result)
     {
         if (c.GetSlotGroup(map).parent.GetType().ToString() == "Replimat.Building_ReplimatHopper")
         {
             // Apply the minimum Hopper refilling threshold only to Replimat Hoppers
             __result &= !map.thingGrid.ThingsListAt(c).Any(t => t.def.EverStorable(false) && t.stackCount >= thing.def.stackLimit * Settings.HopperRefillThresholdPercent);
         }
         else
         {
             // Ignore the threshold for all other storage buildings and stockpiles
             // This ensures compatibility with other mods that control stack refilling thresholds on a more general level (e.g. Hauling Hysteresis, Satisfied Storage)
             __result = __result;
         }
     }
 }
        public override string GetReport()
        {
            IntVec3 cell  = this.job.targetB.Cell;
            Thing   thing = null;

            if (this.pawn.CurJob == this.job && this.pawn.carryTracker.CarriedThing != null)
            {
                thing = this.pawn.carryTracker.CarriedThing;
            }
            else if (base.TargetThingA != null && base.TargetThingA.Spawned)
            {
                thing = base.TargetThingA;
            }
            string result;

            if (thing == null)
            {
                result = "ReportHaulingUnknown".Translate();
            }
            else
            {
                string    text      = null;
                SlotGroup slotGroup = cell.GetSlotGroup(base.Map);
                if (slotGroup != null)
                {
                    text = slotGroup.parent.SlotYielderLabel();
                }
                if (text != null)
                {
                    result = "ReportHaulingTo".Translate(new object[]
                    {
                        thing.Label,
                        text
                    });
                }
                else
                {
                    result = "ReportHauling".Translate(new object[]
                    {
                        thing.Label
                    });
                }
            }
            return(result);
        }
        } // end Transpiler

        // TODO: move this logic to DeepStorage.cs
        public static Thing NullOrLastThingAt(Map map, IntVec3 c, ThingDef def)
        {
            var cds       = (c.GetSlotGroup(map).parent as ThingWithComps).GetComp <CompDeepStorage>();
            var l         = map.thingGrid.ThingsListAtFast(c); // we know it's a slotgroup, so it's valid :p
            var freeSlots = cds.maxNumberStacks;

            Utils.Err(HaulToCellStorageJob, "  testing for def " + def + " at " + c + "; " + freeSlots + " slots.");
            Thing lastThing = null;

            for (var i = 0; i < l.Count; i++)
            {
                if (!l[i].def.EverStorable(false))
                {
                    continue;
                }
                freeSlots--;
                Utils.Mess(HaulToCellStorageJob, "  Checking item " + l[i] + "; now have " + freeSlots + " left.");
                if (!(l[i].def == def))
                {
                    continue;                     // possible problem if defs are same but cannot stack?
                }
                if (lastThing == null)
                {
                    lastThing = l[i];
                }
                else
                {
                    if (l[i].stackCount <= lastThing.stackCount)
                    {
                        lastThing = l[i];
                    }
                }
            }

            if (freeSlots > 0)
            {
                Utils.Err(HaulToCellStorageJob, "  Final count of free slots: " + freeSlots);
                return(null);
            }

            Utils.Warn(HaulToCellStorageJob, "  Final item count: " + (lastThing == null ? "NULL" : lastThing.stackCount.ToString()));
            return(lastThing); // if this is also null, we have a problem :p
        }
Beispiel #18
0
        // This gets checked a lot.  Sometimes the test is done in-place (if will 
        //   need to use the slotGroup later, for example), but when using Harmony 
        //   Transpiler, tests are easier via function call
        // Most of the bulk here is debugging stuff
        public static bool CanStoreMoreThanOneThingAt(Map map, IntVec3 loc, Thing thing) {
            if (!GetDeepStorageOnCell(loc, map, out CompDeepStorage comp))
            {
                return false;
#pragma warning disable CS0162 // Unreachable code detected
                SlotGroup slotGroup = loc.GetSlotGroup(map);
                Log.Warning("CanStoreMoreThanOneThingAt: " + loc + "? false");
                return false;
                if (slotGroup == null) Log.Warning("  null slotGroup");
                else if (slotGroup.parent == null) Log.Warning("  null slotGroup.parent");
                else if (!(slotGroup.parent is ThingWithComps)) Log.Warning("  slotGroup.parent is not ThingWithComps");
                else Log.Warning("  no CompDeepStorage");
                Log.Warning("Just for the record, " + (Scribe.mode == LoadSaveMode.LoadingVars) +
                            (Scribe.mode == LoadSaveMode.PostLoadInit) +
                            Scribe.mode);
                List<Thing> l = map.thingGrid.ThingsListAt(loc);
                foreach (Thing t in l)
                {
                    Log.Error("Did find a " + t.ToString() + " here at " + loc.ToString());
                }
                return false;
            }
            //            Log.Warning("CanStoreMoreThanOneThingAt: " + loc.ToString() + "? true");

            if (comp is CompCachedDeepStorage compCached) {
                bool result = compCached.StorageSettings.AllowedToAccept(thing)
                              && compCached.StackableAt(thing, loc, map);
                return result;
            }

            return true;
            Log.Warning("CanStoreMoreThanOneThingAt: " + loc.ToString() + "? true!");
            List<Thing> lx = map.thingGrid.ThingsListAt(loc);
            foreach (Thing t in lx)
            {
                Log.Error("Did find a " + t.ToString() + " here at " + loc.ToString());
            }
            return true;
#pragma warning restore CS0162 // Unreachable code detected
        }
        public override string GetReport()
        {
            Thing hauledThing = null;

            hauledThing = this.TargetThingA;
            IntVec3   destLoc   = IntVec3.Invalid;
            string    destName  = null;
            SlotGroup destGroup = null;

            if (this.pawn.jobs.curJob.targetB != null)
            {
                destLoc   = this.pawn.jobs.curJob.targetB.Cell;
                destGroup = destLoc.GetSlotGroup(Map);
            }

            this.FailOn(() => !this.pawn.CanReserveAndReach(this.TargetThingA, PathEndMode.ClosestTouch, Danger.Some));

            if (destGroup != null)
            {
                destName = destGroup.parent.SlotYielderLabel();
            }

            string repString;

            if (destName != null && hauledThing != null)
            {
                repString = "ReportHaulingTo".Translate(hauledThing.LabelCap, destName);
            }
            else if (hauledThing != null)
            {
                repString = "ReportHauling".Translate(hauledThing.LabelCap);
            }
            else
            {
                repString = "ReportHauling".Translate();
            }
            return(repString);
        }
Beispiel #20
0
        public override string GetReport()
        {
            IntVec3 cell  = base.job.targetB.Cell;
            Thing   thing = null;

            thing = ((base.pawn.CurJob != base.job || base.pawn.carryTracker.CarriedThing == null) ? base.TargetThingA : base.pawn.carryTracker.CarriedThing);
            if (thing == null)
            {
                return("ReportHaulingUnknown".Translate());
            }
            string    text      = null;
            SlotGroup slotGroup = cell.GetSlotGroup(base.Map);

            if (slotGroup != null)
            {
                text = slotGroup.parent.SlotYielderLabel();
            }
            if (text != null)
            {
                return("ReportHaulingTo".Translate(thing.LabelCap, text));
            }
            return("ReportHauling".Translate(thing.LabelCap));
        }
        public override string GetReport()
        {
            Thing hauledThing = null;

            hauledThing = TargetThingA;
            if (TargetThingA == null)  //Haul Cart
            {
                hauledThing = CurJob.targetC.Thing;
            }
            IntVec3   destLoc   = IntVec3.Invalid;
            string    destName  = null;
            SlotGroup destGroup = null;

            if (pawn.jobs.curJob.targetB != null)
            {
                destLoc   = pawn.jobs.curJob.targetB.Cell;
                destGroup = destLoc.GetSlotGroup();
            }

            if (destGroup != null)
            {
                destName = destGroup.parent.SlotYielderLabel();
            }

            string repString;

            if (destName != null)
            {
                repString = "ReportHaulingTo".Translate(hauledThing.LabelCap, destName);
            }
            else
            {
                repString = "ReportHauling".Translate(hauledThing.LabelCap);
            }

            return(repString);
        }
        public override string GetReport()
        {
            Thing hauledThing = TargetThingA;

            if (TargetThingA == null)  //Haul Cart
            {
                hauledThing = CurJob.targetC.Thing;
            }
            this.FailOn(() => !pawn.CanReach(hauledThing, PathEndMode.ClosestTouch, Danger.Some));
            IntVec3   destLoc   = IntVec3.Invalid;
            string    destName  = null;
            SlotGroup destGroup = null;

            if (pawn.jobs.curJob.targetB != null)
            {
                destLoc   = pawn.jobs.curJob.targetB.Cell;
                destGroup = destLoc.GetSlotGroup();
            }

            if (destGroup != null)
            {
                destName = destGroup.parent.SlotYielderLabel();
            }

            string repString;

            if (destName != null)
            {
                repString = "ReportHaulingTo".Translate(hauledThing.LabelCap, destName);
            }
            else
            {
                repString = "ReportHauling".Translate(hauledThing.LabelCap);
            }

            return(repString);
        }
        // Original LWM DeepStorage Right Click
        // We have to run as Prefix, because we need to intercept the incoming List.
        public static bool OldContextMenu(Vector3 clickPosition, IntVec3 c, Pawn pawn, List<FloatMenuOption> opts)
        {
            if (failsafe++ > 500) runningPatchLogic = false;
            if (runningPatchLogic) return true;

            // Only give nice tidy menu if items are actually in Deep Storage: otherwise, they
            //   are a jumbled mess on the floor, and pawns can only interact with what's on
            //   top until they've cleaned up the mess.
            // I *could* do better and throw away all items below, but whatev's this is good enuf.
            c = IntVec3.FromVector3(clickPosition);

            if ((c.GetSlotGroup(pawn.Map)?.parent as ThingWithComps)?.AllComps
                .FirstOrDefault(x => x is IHoldMultipleThings.IHoldMultipleThings) == null)
            {
                Utils.Warn(RightClickMenu, "Location " + c + " is not in any DSU; continuing.");
                return true; // out of luck, so sorry!
                // Note: also need to handle this case in Postfix!
            }

            failsafe = 0;

            Utils.Err(RightClickMenu, "Testing Location " + c);

            runningPatchLogic = true;

            // TODO: get default set of menus and tidy them away somehow?  This seems to be unnecessary so far.
            // ThingsListAt:
            var workingThingList = c.GetThingList(pawn.Map);
            var origThingList = new List<Thing>(workingThingList);
            workingThingList.Clear();
            // ...other ...things.
            var origPositions = new Dictionary<Thing, IntVec3>();
            var TPeverything = new TargetingParameters
            {
                canTargetBuildings = false,
                canTargetItems = false,
                canTargetFires = true,
                canTargetPawns = true,
                canTargetSelf = true
            };
            foreach (var localTargetInfo in GenUI.TargetsAt_NewTemp(clickPosition, TPeverything))
            {
                if (localTargetInfo.Thing == null)
                {
                    Log.Warning("LWM.DeepStorage: got null target but should only have things?");
                    continue;
                }

                origPositions.Add(localTargetInfo.Thing, localTargetInfo.Thing.Position);
                Utils.Warn(RightClickMenu, "Adding position information for LocalTargetInfo "
                                           + localTargetInfo.Thing);
                SetPosition(localTargetInfo.Thing, IntVec3.Invalid);
            }

            var origParams = new object[] {clickPosition, pawn, opts};
            foreach (var k in origPositions)
            {
                SetPosition(k.Key, k.Value);
                Utils.Mess(RightClickMenu, "  Doing Menu for Target " + k.Key);
                AHlO.Invoke(null, origParams);
                //showOpts(opts);
                SetPosition(k.Key, IntVec3.Invalid);
            }

            foreach (var t in origThingList)
            {
                workingThingList.Add(t);
                Utils.Mess(RightClickMenu, "  Doing Menu for Item " + t);
                AHlO.Invoke(null, origParams);
                //showOpts(opts);
                workingThingList.Remove(t);
            }

            workingThingList.Clear();
            workingThingList.AddRange(origThingList);
            foreach (var t in origPositions) SetPosition(t.Key, t.Value);
            runningPatchLogic = false;

            realList.Clear();
            foreach (var m in opts) realList.Add(m); // got to store it in case anything adjusts it in a different Postfix
            return false;
        }
Beispiel #24
0
        private static bool HaulablePlaceValidator(Thing haulable, Pawn worker, IntVec3 c, out string debugText)
        {
            if (!worker.CanReserveAndReach(c, PathEndMode.OnCell, worker.NormalMaxDanger()))
            {
                debugText = "Could not reserve or reach";
                return(false);
            }
            if (GenPlace.HaulPlaceBlockerIn(haulable, c, worker.Map, true) != null)
            {
                debugText = "Place was blocked";
                return(false);
            }
            var thisIsAPile = c.GetSlotGroup(worker.Map);

            if (thisIsAPile != null)
            {
                if (!thisIsAPile.Settings.AllowedToAccept(haulable))
                {
                    debugText = "Stockpile does not accept";
                    return(false);
                }
            }

            if (!c.Standable(worker.Map))
            {
                debugText = "Cell not standable";
                return(false);
            }
            if (c == haulable.Position && haulable.Spawned)
            {
                debugText = "Current position of thing to be hauled";
                return(false);
            }
            if (c.ContainsStaticFire(worker.Map))
            {
                debugText = "Cell has fire";
                return(false);
            }
            if (haulable != null && haulable.def.BlockPlanting)
            {
                Zone zone = worker.Map.zoneManager.ZoneAt(c);
                if (zone is Zone_Growing)
                {
                    debugText = "Growing zone here";
                    return(false);
                }
            }
            if (haulable.def.passability != Traversability.Standable)
            {
                for (int i = 0; i < 8; i++)
                {
                    IntVec3 adjCell = c + GenAdj.AdjacentCells[i];

                    if (!adjCell.InBounds(worker.Map))
                    {
                        continue;
                    }

                    if (worker.Map.designationManager.DesignationAt(adjCell, DesignationDefOf.Mine) != null)
                    {
                        debugText = "Mining designated nearby";
                        return(false);
                    }
                }
            }

            bool validPositionExists = false;

            var crossGrid = GenAdj.CardinalDirectionsAndInside;

            for (int a = 0; a < crossGrid.CountAllowNull(); a++)
            {
                IntVec3 adjCell = c + crossGrid[a];

                if (!adjCell.InBounds(worker.Map))
                {
                    continue;
                }

                Building restrictedBuildingAdj = adjCell.GetEdifice(worker.Map);
                if (restrictedBuildingAdj != null)
                {
                    if (restrictedBuildingAdj is Building_Door)
                    {
                        break;
                    }
                    if (restrictedBuildingAdj is Building_WorkTable)
                    {
                        thisIsAPile = adjCell.GetSlotGroup(worker.Map);

                        if (thisIsAPile != null)
                        {
                            if (thisIsAPile.Settings.AllowedToAccept(haulable))
                            {
                                validPositionExists = true;
                            }
                        }
                    }
                }
                else
                {
                    validPositionExists = true;
                }
            }

            if (!validPositionExists)
            {
                debugText = "No valid position could be found.";
                return(false);
            }

            Building edifice = c.GetEdifice(worker.Map);

            if (edifice != null)
            {
                if (edifice is Building_Trap)
                {
                    debugText = "It's a trap.";
                    return(false);
                }

                if (edifice is Building_WorkTable)
                {
                    debugText = "Worktable here.";
                    return(false);
                }
            }

            debugText = "OK";
            return(true);
        }
        // allows to place items to container stacks
        public static bool TryPlaceDirect(Thing thing, IntVec3 loc, out Thing resultingThing,
            Action<Thing, int> placedAction = null)
        {
            #region CONTAINER CASE

            var container =
                Find.ThingGrid.ThingsListAt(loc).Find(building => building is Container && building.Spawned) as
                    Container;
            if (container != null)
            {
                // stackables (like resources)
                if (thing.def.stackLimit > 1)
                {
                    foreach (var item in container.StoredItems)
                    {
                        // if item can stack with another
                        // Required, because thing reference is changed to the absorber, if absorbed
                        if (item.TryAbsorbStack(thing, true))
                        {
                            // former item gets absorbed and destroyed
                            resultingThing = item;
                            // hide texture and label of the stored item
                            container.HideItem(resultingThing);
                            return true;
                        }
                    }
                }

                resultingThing = GenSpawn.Spawn(thing, loc);
                // hide texture and label of the stored item
                container.HideItem(resultingThing);

                return true;
            }

            #endregion

            #region VANILLA CASE

            // used to keep original thing reference
            var initialThing = thing;
            var flag = false;
            if (thing.stackCount > thing.def.stackLimit)
            {
                thing = thing.SplitOff(thing.def.stackLimit);
                flag = true;
            }
            if (thing.def.stackLimit > 1)
            {
                var thingList = loc.GetThingList();
                var i = 0;
                while (i < thingList.Count)
                {
                    var thing3 = thingList[i];
                    if (!thing3.CanStackWith(thing))
                    {
                        i++;
                    }
                    else
                    {
                        var stackCount = thing.stackCount;
                        if (thing3.TryAbsorbStack(thing, true))
                        {
                            resultingThing = thing3;
                            placedAction?.Invoke(thing3, stackCount);
                            return !flag;
                        }
                        resultingThing = null;
                        if (placedAction != null && stackCount != thing.stackCount)
                        {
                            placedAction(thing3, stackCount - thing.stackCount);
                        }
                        if (initialThing != thing)
                        {
                            initialThing.TryAbsorbStack(thing, false);
                        }
                        return false;
                    }
                }
            }
            resultingThing = GenSpawn.Spawn(thing, loc);
            placedAction?.Invoke(thing, thing.stackCount);
            var slotGroup = loc.GetSlotGroup();
            slotGroup?.parent?.Notify_ReceivedThing(resultingThing);
            return !flag;

            #endregion
        }
Beispiel #26
0
        protected static bool Prefix(IntVec3 c, Map map, Thing thing, ref bool __result)
        {
            Utils.Err(NoStorageBlockerseIn, "Looking for blockers for " + thing + " at " + c);
            // Check if storage location is in an uber-storage building:
            SlotGroup       slotGroup = c.GetSlotGroup(map);
            CompDeepStorage cds       = null;

            if (slotGroup == null || !(slotGroup?.parent is ThingWithComps) ||
                (cds = (slotGroup.parent as ThingWithComps).TryGetComp <CompDeepStorage>()) == null)
            {
                //                Log.Warning("  ...letting vanilla handle it.");
                return(true); // normal spot, NoStorageBlockersIn() will handle it
            }
            //TODO: Make this IHoldMultipleThings
//            __result = false; // NoStorageBlockersIn returns false if there's a blocker
            // Default to having a blocker unless EVERYTHING is okay
            //  (We return false from this Patch function to skip original method)
            __result = cds.StackableAt(thing, c, map);
            Utils.Warn(NoStorageBlockerseIn, "Final result for " + thing + " at " + c + ": " + __result);
            return(false);

#if false
            // If there is a maximum size of items that will fit in the unit, quit:
            if (cds.limitingFactorForItem > 0f)
            {
                if (thing.GetStatValue(cds.stat) > cds.limitingFactorForItem)
                {
                    Utils.Warn(NoStorageBlockerseIn, "Thing has " + cds.stat + " of " +
                               thing.GetStatValue(StatDefOf.Mass) + " but max allowed is " +
                               cds.limitingFactorForItem);
                    return(false);
                }
            }
            // We will usually care how many stacks can fit here:
            var maxStacks = cds.maxNumberStacks;
            // If maxTotalMass is set, we will keep track of how much "room" we have as well:
            float totalAmountHereSoFar = 0f;
            if (cds.limitingTotalFactorForCell > 0f)
            {
                totalAmountHereSoFar = thing.GetStatValue(cds.stat);
            }

            var          objInStack = 0;
            List <Thing> list       = map.thingGrid.ThingsListAt(c);
            for (int i = 0; i < list.Count; i++)   //loop thru cell's contents
            {
                Thing thing2 = list[i];
                Utils.Warn(NoStorageBlockerseIn, "  ...checking: does " + thing2 + " block?");
                if (thing2.def.EverStorable(false))   // an "item" as it were
                {
                    if (cds.limitingTotalFactorForCell > 0f)
                    {
                        totalAmountHereSoFar += (thing2.GetStatValue(cds.stat) * thing2.stackCount);
                        Utils.Warn(NoStorageBlockerseIn, "  added 'mass' " + thing2.GetStatValue(cds.stat) +
                                   " to running total " + totalAmountHereSoFar + " / " + cds.limitingTotalFactorForCell
                                   + "(" + (objInStack + 1) + " v " + cds.minNumberStacks + ")");
                        if (totalAmountHereSoFar > cds.limitingTotalFactorForCell &&
                            objInStack + 1 >= cds.minNumberStacks)   // Must accept minimum (haven't incremented objInStack yet)
                                                                     // but if reached minimum and over capacity, cannot store here
                        {
                            Utils.Warn(NoStorageBlockerseIn, "  BLOCKS: Over mass limit ("
                                       + cds.limitingTotalFactorForCell + ")");
                            return(false);
                        }
                    }
                    if (!thing2.CanStackWith(thing))
                    {
                        objInStack++;
                    }
                    else if (thing2.stackCount >= thing.def.stackLimit)
                    {
                        objInStack++;
                    }
                    else // it can stack and there's room in the stack for more...
                    {    // go ahead and get out of here with the good news!
                        __result = true;
                        Utils.Warn(NoStorageBlockerseIn, thing.ToString() + " at " + c.ToString() + ": " + __result);
                        return(false);
                    }
                    if (objInStack >= maxStacks)
                    {
                        return(false);
                    }
                    continue;
                }
                if (thing2.def.entityDefToBuild != null && thing2.def.entityDefToBuild.passability != Traversability.Standable)
                {
                    Utils.Warn(NoStorageBlockerseIn, thing.ToString() + " at " + c.ToString() + ": " + __result);
                    return(false);
                }
                if (thing2.def.surfaceType == SurfaceType.None && thing2.def.passability != Traversability.Standable)
                {
                    Utils.Warn(NoStorageBlockerseIn, thing.ToString() + " at " + c.ToString() + ": " + __result);
                    return(false);
                }
            }
            //You know what I can't get running in Linux?  Monodevelop's debugger.
            //Log.Warning("No storage blockers for "+thing.ToString()+" in "+slotGroup.ToString());
            __result = true; // no blockers after all!
            Utils.Warn(NoStorageBlockerseIn, thing.ToString() + " at " + c.ToString() + ": " + __result);
            return(false);
#endif
        }
Beispiel #27
0
        // Always use this if you are placing an item.
        /// <summary>
        /// Place a Thing (onto the ground or into a proper receptacle)
        /// Any time ANY PRF building tries to place an item, this is THE way to do it:
        ///   It checks if the space is clear, it checks for conveyor belts, in checks
        ///   for other storage mods (well, Deep Storage, anyway).  It does all the
        ///   things!
        /// </summary>
        /// <returns><c>true</c>, if item was placed, <c>false</c> if it could not.</returns>
        /// <param name="placer">The PRF_Building doing the placing</param>
        /// <param name="t">Thing to place.</param>
        /// <param name="cell">Where to place.</param>
        /// <param name="map">Map.</param>
        /// <param name="forcePlace">If set to <c>true</c>, forces placing. For when
        ///   you absolutely positively have to put it down.</param>
        public static bool PRFTryPlaceThing(this IPRF_Building placer, Thing t, IntVec3 cell, Map map,
                                            bool forcePlace = false)
        {
            if (!cell.InBounds(map))
            {
                Log.Error("PRF Error Attempting to place Thing out of bounds.");
                return(false);
            }

            // Storage:
            SlotGroup slotGroup = cell.GetSlotGroup(map);

            if (slotGroup != null)
            {
                Debug.Warning(Debug.Flag.PlaceThing, "Placing " + t + " in slotGroup: " + slotGroup.parent + " at " + cell);
                if (slotGroup.parent is IPRF_Building)
                {
                    if (placer.PlaceThingNextBuilding((slotGroup.parent as IPRF_Building),
                                                      t, cell, map))
                    {
                        Debug.Message(Debug.Flag.PlaceThing, "  which is owned by PRF " + slotGroup.parent);
                        return(true);
                    }
                    if (forcePlace)
                    {
                        goto ForcePlace;
                    }
                    return(false);
                }
                if (placer.PlaceThingInSlotGroup(t, slotGroup, cell, map))
                {
                    return(true);
                }
                if (forcePlace)
                {
                    goto ForcePlace;
                }
                return(false);
            }
            Debug.Warning(Debug.Flag.PlaceThing, "Place request: " + placer == null ? "NoPlacer" : placer.ToString() + " is trying to place " + t + " at " + cell);
            // Search through all items in cell: see if any will absorb
            //   our thing.  If we find a PRF_Building, stop looking and
            //   try to pass it on.
            bool cellIsImpassible = false;

            foreach (Thing otherThing in map.thingGrid.ThingsListAt(cell))
            {
                if (otherThing.TryAbsorbStack(t, true))
                {
                    Debug.Message(Debug.Flag.PlaceThing, "  absorbed by " + otherThing);
                    placer.EffectOnPlaceThing(otherThing); // I think?
                    return(true);
                }
                if (otherThing.def.passability == Traversability.Impassable)
                {
                    cellIsImpassible = true;
                }
                if (otherThing is IPRF_Building)
                {
                    if (placer.PlaceThingNextBuilding((otherThing as IPRF_Building),
                                                      t, cell, map))
                    {
                        Debug.Message(Debug.Flag.PlaceThing, placer +
                                      " gave " + t + " to " + otherThing);
                        placer.EffectOnPlaceThing(t);
                        return(true);
                    }
                    // Continue loop - may be more than 1 PRF_Building here
                }
            }
            // There is no IPRF Building to take this from us
            if (cellIsImpassible)
            {
                Debug.Message(Debug.Flag.PlaceThing, "  cell is impassable.");
                if (forcePlace)
                {
                    goto ForcePlace;
                }
                return(false);
            }
            // The cell is not impassible! Try to place:
            if (CallNoStorageBlockersIn(cell, map, t))
            {
                Debug.Message(Debug.Flag.PlaceThing, "  placing directly.");
                bool wasSpawned = t.Spawned;
                if (wasSpawned)
                {
                    t.DeSpawn();
                }
                if (!GenPlace.TryPlaceThing(t, cell, map, ThingPlaceMode.Direct))
                {
                    // some of the stack
                    Debug.Message(Debug.Flag.PlaceThing, "  some absorbed, still have " + t.stackCount + " left");
                    // I think this is safe, as it shoudl still have its position?
                    if (wasSpawned)
                    {
                        GenPlace.TryPlaceThing(t, t.Position, map, ThingPlaceMode.Near);
                    }
                    placer.EffectOnPlaceThing(t);
                    if (forcePlace)
                    {
                        goto ForcePlace;
                    }
                    return(false);
                }
                placer.EffectOnPlaceThing(t);
                if (placer.ForbidOnPlacing(t))
                {
                    t.SetForbidden(true, false);
                }
                return(true);
            }
            if (!forcePlace)
            {
                return(false);
            }
ForcePlace:
            Debug.Warning(Debug.Flag.PlaceThing, "  Placement is forced!");
            if (t.Spawned)
            {
                t.DeSpawn();
            }
            GenPlace.TryPlaceThing(t, cell, map, ThingPlaceMode.Near);
            placer.EffectOnPlaceThing(t);
            if (placer.ForbidOnPlacing(t))
            {
                t.SetForbidden(true, false);
            }
            return(true);
        }
        // We have to run as Prefix, because we need to intercept the incoming List.
        public static bool Prefix(Vector3 clickPosition, IntVec3 c, Pawn pawn, List <FloatMenuOption> opts,
                                  bool runningAJGWO, bool drafted /*only if runningAJGWO*/)
        {
            Utils.Mess(RightClickMenu, "" + (runningAJGWO?"AddJobGiverWorkOrders":"AddHumanlikeOrders") +
                       " called.  Currently "
                       + (runningPatchLogic?"":" not ") + "running special Patch Logic");
            if (runningAJGWO)
            {
                return(true);
            }
            if (failsafe++ > 500)
            {
                runningPatchLogic = false;
            }
            if (runningPatchLogic)
            {
                return(true);
            }
            // Only give nice tidy menu if items are actually in Deep Storage: otherwise, they
            //   are a jumbled mess on the floor, and pawns can only interact with what's on
            //   top until they've cleaned up the mess.
            // I *could* do better and throw away all items below, but whatev's this is good enuf.
            if (!runningAJGWO)
            {
                clickPos = clickPosition;
                c        = IntVec3.FromVector3(clickPos);
            }
            if (((c.GetSlotGroup(pawn.Map)?.parent) as ThingWithComps)?.AllComps
                .FirstOrDefault(x => x is IHoldMultipleThings.IHoldMultipleThings) == null)
            {
                Utils.Warn(RightClickMenu, "Location " + c + " is not in any DSU; continuing.");
                return(true); // out of luck, so sorry!
                // Note: also need to handle this case in Postfix!
            }
            failsafe = 0;

            Utils.Err(RightClickMenu, "Testing Location " + c);

            runningPatchLogic = true;

            // TODO: get default set of menus and tidy them away somehow?  This seems to be unnecessary so far.
            /************* Move all things away **************/
            // ThingsListAt:
            List <Thing> workingThingList = c.GetThingList(pawn.Map);
            List <Thing> origThingList    = new List <Thing>(workingThingList);

            workingThingList.Clear();
            // ...other ...things.
            Dictionary <Thing, IntVec3> origPositions = new Dictionary <Thing, IntVec3>();
            TargetingParameters         TPeverything  = new TargetingParameters();

            TPeverything.canTargetBuildings = false; //already got it
            TPeverything.canTargetItems     = false; //already got it
            TPeverything.canTargetFires     = true;  //??
            TPeverything.canTargetPawns     = true;
            TPeverything.canTargetSelf      = true;
            foreach (var localTargetInfo in GenUI.TargetsAt(clickPos, TPeverything))
            {
                if (localTargetInfo.Thing == null)
                {
                    Log.Warning("LWM.DeepStorage: got null target but should only have things?");
                    continue;
                }
                origPositions.Add(localTargetInfo.Thing, localTargetInfo.Thing.Position);
                Utils.Warn(RightClickMenu, "Adding position information for LocalTargetInfo "
                           + localTargetInfo.Thing);
                SetPosition(localTargetInfo.Thing, IntVec3.Invalid);
            }
            /*****************  Do magic ****************/
            object[] origParams;
            if (runningAJGWO)
            {
                origParams = new object[] { c, pawn, opts, drafted };
            }
            else
            {
                origParams = new object[] { clickPos, pawn, opts };
            }
            foreach (var k in origPositions)
            {
                SetPosition(k.Key, k.Value);
                Utils.Mess(RightClickMenu, "  Doing Menu for Target " + k.Key);
                if (runningAJGWO)
                {
                    AJGWO.Invoke(null, origParams);
                }
                else
                {
                    AHlO.Invoke(null, origParams);
                }
                //showOpts(opts);
                SetPosition(k.Key, IntVec3.Invalid);
            }
            foreach (var t in origThingList)
            {
                workingThingList.Add(t);
                Utils.Mess(RightClickMenu, "  Doing Menu for Item " + t);
                AHlO.Invoke(null, origParams);
                //showOpts(opts);
                workingThingList.Remove(t);
            }

            /************ Cleanup: Put everything back! ***********/
            workingThingList.Clear();
            foreach (var t in origThingList)
            {
                workingThingList.Add(t);
            }
            foreach (var t in origPositions)
            {
                SetPosition(t.Key, t.Value);
            }
            runningPatchLogic = false;
            realList.Clear();
            foreach (var m in opts)
            {
                realList.Add(m); // got to store it in case anything adjusts it in a different Postfix
            }
            return(false);
        } // end Prefix
        public static bool Prefix(Vector3 clickPos, Pawn pawn, List <FloatMenuOption> opts)
        {
            if (!Settings.useDeepStorageRightClickLogic)
            {
                return(true);
            }
//                return Patch_FloatMenuMakerMap.Prefix(clickPos,IntVec3.Invalid,pawn,opts,false,false);

            // if expicitly told to run vanilla, run vanilla.
            //   (note vanilla may have any number of mods attached)
            if (runVanillaAHlO)
            {
                Utils.Warn(RightClickMenu, "-------Running Vanilla AddHumanlikeOrders" + pawn + "-------");
                return(true);
            }
            // if not in storage, don't worry about it:
            IntVec3 clickCell = IntVec3.FromVector3(clickPos);

            if (!Utils.CanStoreMoreThanOneThingAt(pawn.Map, clickCell))
            {
                Utils.Warn(RightClickMenu, "-----Running Vanilla AddHumanlikeOrders" + pawn + " - not in storage-----");
                return(true);
            }
            Utils.Warn(RightClickMenu, "-----Running Custom AddHumanlikeOrders for " + pawn + "-----");
            // We will fill listOfOptionsWeFilled - this lets us properly handle other mods'
            //   right click modifications (we will use listOfOptionsWeFilled in our postfix
            //   to provide the actual result). In the meantime, we use listOfOptions as our
            //   list - we will move everything over at the end.
            // Why?  Because we have to move over our final result in the Postfix
            List <FloatMenuOption> listOfOptions = new List <FloatMenuOption>();

            // Prepare Faerie to accept pawns/etc.
            thingsInRealmOfFaerie.Clear();

            // get menu with no items.  This will include commands such as "clean dirt."  I think.
            // and dealing with fire.  I think.  And pawns.  Definitely dealing with pawns.

            /*var index = pawn.Map.cellIndices.CellToIndex(cpos.ToIntVec3());
             * var listArray = (List<Thing>[]) thingListTG.GetValue(pawn.Map.thingGrid);
             * var origList = listArray[index];
             *
             * listArray[index] = new List<Thing> {thingList[i]};
             * rows[i] = new DSGUI_ListItem(pawn, thingList[i], cpos, boxHeight);
             * listArray[index] = origList;
             */
            //   Clear thingsList
            if (mapOfCachedThingGrid != pawn.Map)
            {
                mapOfCachedThingGrid     = pawn.Map;
                cachedThingGridThingList = (List <Thing>[])thingGridThingList.GetValue(pawn.Map.thingGrid);
            }
            var          index    = pawn.Map.cellIndices.CellToIndex(clickCell);
            List <Thing> origList = cachedThingGridThingList[index];

            cachedThingGridThingList[index] = tmpEmpty;

            runVanillaAHlO = true;
            Utils.Mess(RightClickMenu, "Get menu with no items: invoke vanilla:");
//            List<Thing> thingList=clickCell.GetThingList(pawn.Map);
//            List<Thing> tmpList=new List<Thing>(thingList);
//            thingList.Clear();
            AHlO(clickPos, pawn, listOfOptions);

            /* var origParams=new object[] {clickPos, pawn, listOfOptions};
             * AHlO.Invoke(null, origParams);*/
            runVanillaAHlO = false;
            // return things
            cachedThingGridThingList[index] = origList;
            Utils.Mess(RightClickMenu, "  ->" + String.Join("; ", listOfOptions));
//            thingList.AddRange(tmpList);
//            ReturnThingsFromFaerie();
            // get sorted list of all things in dsu
            List <Thing> allThings = clickCell.GetSlotGroup(pawn.Map).HeldThings.OrderBy(t => t.LabelCap).ToList();

            // Multilpe Options here, depending on size of allThings.
            //   6 or fewer => should just display each set of options
            //   7-12       => show entry for each, with options
            //   LOTS       => open f***ing window w/ search options, etc.
            // for each thing(mod label) in storage, add menu entry
            // ...for now, just print them all:
            for (int i = 0; i < allThings.Count; i++)
            {
                Thing t = allThings[i];

/*                int howManyOfThis=1;
 *              while (i<allThings.Count-1 && t.Label==allThings[i+1].Label) {
 *                  howManyOfThis++;
 *                  i++;
 *              }
 *              string label;
 *              if (howManyOfThis==1)
 *                  label=t.Label;
 *              else
 *                  label=howManyOfThis.ToString()+" x "+t.Label;//TODO: translate
 *              //TODO: what if no option for this item????
 */
                GeneratePawnOptionsFor(pawn, t, listOfOptions);
//                listOfOptions.Add(MakeMenuOptionFor(pawn, t, howManyOfThis));
            }
            listOfOptionsWeFilled = listOfOptions;
            #if DEBUG
            if (Utils.showDebug[(int)RightClickMenu])
            {
                for (int ijk = 0; ijk < 1000; ijk++)
                {
                    Log.Message("pausing log...");
                }
            }
            #endif
            return(false);
            //return Patch_FloatMenuMakerMap.Prefix(clickPos,IntVec3.Invalid,pawn,opts,false,false);
        }
 // duplicated to make changes
 public bool IsValidStorageFor(IntVec3 c, Thing storable)
 {
     // call duplicated to make changes
     if (!WorkGiver_HaulGeneral.NoStorageBlockersIn(c, storable))
     {
         return false;
     }
     SlotGroup slotGroup = c.GetSlotGroup();
     return slotGroup != null && slotGroup.Settings.AllowedToAccept(storable);
 }
Beispiel #31
0
 public static bool TryFindStoreCellNearColonyDesperate(Thing item, Pawn carrier, out IntVec3 storeCell)
 {
     if (StoreUtility.TryFindBestBetterStoreCellFor(item, carrier, carrier.Map, StoragePriority.Unstored, carrier.Faction, out storeCell, true))
     {
         return(true);
     }
     for (int i = -4; i < 20; i++)
     {
         int     num    = (i >= 0) ? i : Rand.RangeInclusive(0, 4);
         IntVec3 intVec = carrier.Position + GenRadial.RadialPattern[num];
         if (intVec.InBounds(carrier.Map) && carrier.Map.areaManager.Home[intVec] && carrier.CanReach(intVec, PathEndMode.ClosestTouch, Danger.Deadly, false, TraverseMode.ByPawn) && intVec.GetSlotGroup(carrier.Map) == null && StoreUtility.IsGoodStoreCell(intVec, carrier.Map, item, carrier, carrier.Faction))
         {
             storeCell = intVec;
             return(true);
         }
     }
     if (RCellFinder.TryFindRandomSpotJustOutsideColony(carrier.Position, carrier.Map, carrier, out storeCell, (IntVec3 x) => x.GetSlotGroup(carrier.Map) == null && StoreUtility.IsGoodStoreCell(x, carrier.Map, item, carrier, carrier.Faction)))
     {
         return(true);
     }
     storeCell = IntVec3.Invalid;
     return(false);
 }
        // duplicated to make changes (added container support)
        public bool TryPlaceDirect(Thing thing, IntVec3 loc, out Thing resultingThing)
        {
            // boolean success indicator
            bool flag = false;

            // container code part
            List<Thing> list = Find.ThingGrid.ThingsListAt(loc);
            if (list.Exists(storage => storage.TryGetComp<CompContainer>() != null))
            {
                resultingThing = null;

                // stackables (like resources)
                if (thing.def.stackLimit > 1)
                {
                    foreach (Thing item in list)

                    {
                        if (!item.CanStackWith(thing))
                        {
                            continue;
                        }
                        // if item can stack with another
                        else
                        {
                            // Required, because thing reference is changed to the absorber, if absorbed
                            Thing t = thing;
                            if (item.TryAbsorbStack(thing, true))
                            {
                                // Clean up to prevent haulables lists overflow
                                RemoveHaulableFromLists(t);
                                // it gets absorbed and destroyed
                                resultingThing = item;
                                return !flag;
                            }
                        }
                    }
                }

                resultingThing = GenSpawn.Spawn(thing, loc);

                // Clean up to prevent haulables lists overflow
                RemoveHaulableFromLists(thing);

                return !flag;
            }

            // vanilla code part
            if (thing.stackCount > thing.def.stackLimit)
            {
                thing = thing.SplitOff(thing.def.stackLimit);
                flag = true;
            }
            if (thing.def.stackLimit > 1)
            {
                List<Thing> thingList = loc.GetThingList();
                int i = 0;
                while (i < thingList.Count)
                {
                    Thing thing2 = thingList[i];
                    if (!thing2.CanStackWith(thing))
                    {
                        i++;
                    }
                    else
                    {
                        // Required, because thing reference is changed to the absorber, if absorbed
                        Thing t = thing;
                        if (thing2.TryAbsorbStack(thing, true))
                        {
                            // Clean up to prevent haulables lists overflow
                            RemoveHaulableFromLists(t);
                            resultingThing = thing2;
                            return !flag;
                        }
                        resultingThing = null;
                        return false;
                    }
                }
            }

            resultingThing = GenSpawn.Spawn(thing, loc);
            // Clean up to prevent haulables lists overflow
            RemoveHaulableFromLists(thing);

            SlotGroup slotGroup1 = loc.GetSlotGroup();
            if (slotGroup1 != null && slotGroup1.parent != null)
            {
                slotGroup1.parent.Notify_ReceivedThing(resultingThing);
            }
            return !flag;
        }
Beispiel #33
0
        static void Postfix(ref bool __result, Thing __state, IntVec3 loc, Map map,
                            ref Thing resultingThing, Action <Thing, int> placedAction)
        {
            Thing thing = __state;
            // First check if we're dropping off in Deep Storage:
            SlotGroup slotGroup = loc.GetSlotGroup(map);

            if (slotGroup == null || !(slotGroup?.parent is ThingWithComps) ||
                ((ThingWithComps)slotGroup.parent).TryGetComp <CompDeepStorage>() == null)
            {
                Utils.Warn(TryPlaceDirect, "  (placed " + __state + " NOT in Deep Storage: with result " + __result + ")");
                return;
            }

            if (resultingThing != null)
            {
                // Two cases here if resultingThing exists:
                //   1. There's a new object on the map
                //        (so resultingThing is the original thing, we don't have anyting to put down)
                //   2. Everything we put down was able to stack with something on the map
                //        (so nothing else to put down!)
                //   (case three - something weird going on possibly involving carrying?)
                //        (all bets are off anyway >_< )
                // Probably, the pawn put down what they were carrying, and all is good.
                Utils.Warn(TryPlaceDirect, "  successfully placed " + resultingThing.stackCount + resultingThing.ToString() + " (" + __result + ")");
                Utils.TidyStacksOf(resultingThing);
                return;
            }
            // Ok, so we still have something we want to place, and it goes in Deep Storage
            //   (We will still return __result=false if we can't place everything in the desired space.)

            Utils.Err(TryPlaceDirect, "LWM:TryPlaceDirect tried to place " + thing.ToString() + " in " + slotGroup.ToString());

            // Let's see if there's still room in the Deep Storage area the pawn is using:
            List <Thing> list            = map.thingGrid.ThingsListAt(loc);
            int          maxNumberStacks = ((ThingWithComps)slotGroup.parent).GetComp <CompDeepStorage>().maxNumberStacks;
            // We know there was at least one thing here, and it either doesn't stack with our thing
            //   or its stack is full.
            // So, we go thru the items that are there
            int thingsHere = 0;

            for (int i = 0; i < list.Count; i++)
            {
                Thing thing2 = list[i];
                if (!thing2.def.EverStorable(false))
                {
                    //not an object we count
                    continue;
                }
                thingsHere++;
                Utils.Warn(TryPlaceDirect, "  Currently there are " + thingsHere +
                           " things here, max: " + maxNumberStacks);
                if (thingsHere == 1)
                {
                    //  (should be safe because 1st haulable stack would already have been
                    //   tested by default vanilla function)
                    continue;
                }
                //unfortunately, we have to duplicate some of the original code:
                if (!thing2.CanStackWith(thing))
                {
                    Utils.Warn(TryPlaceDirect, "...ignoring \"other\" stack " + thing2.ToString());
                    continue;  // am carrying wood, but this is sheep.  Or rock, whatever.
                }
                // Okay, can stack.
                if (thing2.stackCount >= thing2.def.stackLimit)
                {
                    Utils.Warn(TryPlaceDirect, "...ignoring full stack " + thing2.ToString());
                    continue; // stack is full.
                }
                // Put some down in the non-full stack!
                var origStackCount = thing.stackCount;
                if (thing2.TryAbsorbStack(thing, true))
                {
                    // the "thing2" stack could hold everything we wanted to put down!
                    Utils.Warn(TryPlaceDirect, "... Object " + thing2.ToString() + " absorbed ALL of " + thing.ToString());
                    resultingThing = thing2;
                    // Okay, I like this notation:  only call if non-null:
                    placedAction?.Invoke(thing2, origStackCount);
                    Utils.TidyStacksOf(thing2);
                    __result = true; // Could put down everything!
                    return;
                }
                Utils.Warn(TryPlaceDirect, "... Object " + thing2.ToString() + " absorbed SOME of " + thing.ToString());
                // Since we tried to put some down in that stack, do we do placedAction?
                if (placedAction != null && origStackCount != thing.stackCount)
                {
                    placedAction(thing2, origStackCount - thing.stackCount);
                }
                // ...but there's still more to place, so keep going:
            } // end loop of objects in this location
            if (thingsHere >= maxNumberStacks)   // Ran out of room in the storage object but still want to put stuff down ;_;
            {
                Utils.Warn(TryPlaceDirect, "...But ran out of stack space here: all " + maxNumberStacks + " filled");
                __result = false;
                return; // no need to TidyStacks here - they have to be all full
            }
            // if we reach here, we found an empty space,
            //   so put something down!
            Utils.Warn(TryPlaceDirect, "...Found empty stack space at " + loc.ToString() +
                       ". Trying to create from " + thing.ToString());
            // In some circumstances (e.g., butchering a large animal), a pawn can be putting
            //   down way more than stackLimit of something.  We deal with that scenario here
            //////////////////////// NOTE:  POSSIBLE PROBLEM: ////////////////////
            //   resultingThing is set to only the last thing here - it's possible we miss something
            //   important by placing as much as we can at once:
            while (thing.stackCount > thing.def.stackLimit)  // put down part of a carried load?
            {
                Thing thing2 = thing.SplitOff(thing.def.stackLimit);
                resultingThing = GenSpawn.Spawn(thing2, loc, map);
                Utils.Warn(TryPlaceDirect, "...put down one full stack ("
                           + resultingThing.ToString() + "); " + thing.stackCount + " left");
                placedAction?.Invoke(thing2, thing2.stackCount);
                thingsHere++;
                if (thingsHere >= maxNumberStacks)   // Oh dear.  There was still at least SOME left...
                {
                    Utils.Warn(TryPlaceDirect, "...But ran out of stack space here: all "
                               + maxNumberStacks + " filled but still have " + thing.stackCount + " left");
                    __result = false; // couldn't put things down
                    return;           // no need to TidyStacks - they all have to be full
                }
            }
            // Either Spawn the thing (or Spawn the final part of the thing):
            resultingThing = GenSpawn.Spawn(thing, loc, map);
            __result       = true; // nothing unplaced!

            Utils.Warn(TryPlaceDirect, "...created " + resultingThing.ToString());
            placedAction?.Invoke(thing, thing.stackCount); // Okay, I like this notation
            Utils.TidyStacksOf(resultingThing);
            return;                                        // with __result=!flag (probably "true");
        } // end TryPlaceDirect's Postfix