public static bool GetDeepStorageOnCell(IntVec3 cell, Map map, out CompDeepStorage compDeepStorage) { if (HasDeepStorageComp(map?.haulDestinationManager?.SlotGroupAt(cell), out compDeepStorage)) { return true; } compDeepStorage = null; return false; }
public static HashSet<Thing> TopThingInDeepStorage = new HashSet<Thing>(); // for display public static bool HasDeepStorageComp(SlotGroup slotGroup, out CompDeepStorage compDeepStorage) { if (slotGroup?.parent is ThingWithComps thingWithComps && (compDeepStorage = thingWithComps.TryGetComp<CompDeepStorage>()) != null) { return true; } compDeepStorage = null; return false; }
} // end Transpiler // TODO: move this logic to DeepStorage.cs public static Thing NullOrLastThingAt(Map map, IntVec3 c, ThingDef def) { CompDeepStorage 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 (int 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 }
// LWM rewrote most of this method to meet their implementation of CompDeepStorage private void DisplayHeaderInfo(ref float curY, float width, Building_Storage cabinet, int numCells, List <Thing> itemsList) { CompDeepStorage cds = cabinet.GetComp <CompDeepStorage>(); if (cds == null) { return; // what are we even doing here, mmm? } Rect rect = new Rect(0f, curY, width, 22f); if (itemsList.Count < 1) { Widgets.Label(rect, "NoItemsAreStoredHere".Translate()); curY += 22; return; } float itemsTotalMass = 0; // or Bulk for CE ;p for (int i = 0; i < itemsList.Count; i++) { itemsTotalMass += itemsList[i].GetStatValue(cds.stat, true) * (float)itemsList[i].stackCount; } if (cds.limitingTotalFactorForCell > 0f) { Widgets.Label(rect, "LWM.ContentHeaderOneOf".Translate(itemsList.Count.ToString(), cds.stat.ToString(), itemsTotalMass.ToString("0.##"), (cds.limitingTotalFactorForCell * numCells).ToString("0.##"))); } else { Widgets.Label(rect, "LWM.ContentHeaderOne".Translate(itemsList.Count.ToString(), cds.stat.ToString(), itemsTotalMass.ToString("0.##"))); } curY += 22f; }
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 }
static bool OverCapacity(Map map, Thing thing, ref StoragePriority storagePriority) { if (!thing.Spawned) { return(false); } if (storagePriority == StoragePriority.Unstored) { return(false); } CompDeepStorage cds = (thing.Position.GetSlotGroup(map)?.parent as ThingWithComps)?.GetComp <CompDeepStorage>(); List <Thing> l; // What if it's a slotGroup put down after someone moved/destroyed a DSU? // Because we CAN still end up with more than one thing on the ground. if (cds == null) { l = map.thingGrid.ThingsListAt(thing.Position); for (int i = 0; i < l.Count; i++) { if (l[i].def.EverStorable(false)) { if (thing == l[i]) { return(false); } Utils.Warn(ShouldRemoveFromStorage, "LWM.DeepStorage: " + thing.stackCount + thing + " is not in a DSU and there is already a thing at " + thing.Position); storagePriority = StoragePriority.Unstored; return(true); } } } if (cds.limitingFactorForItem > 0f) { if (thing.GetStatValue(cds.stat) > cds.limitingFactorForItem) { Utils.Warn(ShouldRemoveFromStorage, "LWM.DeepStorage: " + thing.stackCount + thing + " is too heavy for DSU at " + thing.Position); storagePriority = StoragePriority.Unstored; return(true); } } float totalWeightStoredHere = 0f; //mass, or bulk, etc. var stacksStoredHere = 0; l = map.thingGrid.ThingsListAt(thing.Position); for (int i = 0; i < l.Count; i++) { Thing thingInStorage = l[i]; // TODO: Decide how to handle weight: if thing is stackable, do I want to take some out, if it goes over? if (thing == thingInStorage) { return(false); // it's here, and not over capacity yet! } if (thingInStorage.def.EverStorable(false)) // an "item" we care about { stacksStoredHere++; if (cds.limitingTotalFactorForCell > 0f) { totalWeightStoredHere += thingInStorage.GetStatValue(cds.stat) * thingInStorage.stackCount; if (totalWeightStoredHere > cds.limitingTotalFactorForCell && stacksStoredHere >= cds.minNumberStacks) { Utils.Warn(ShouldRemoveFromStorage, "LWM.DeepStorage: " + thing.stackCount + thing + " is over weight capacity at " + thing.Position); storagePriority = StoragePriority.Unstored; return(true); // this takes us to capacity, and we haven't hit thing } } if (stacksStoredHere >= cds.maxNumberStacks) // breaks if minNumberStacks > maxNumberStacks. I'm okay with this { Utils.Warn(ShouldRemoveFromStorage, "LWM.DeepStorage: " + thing.stackCount + thing + " is over capacity at " + thing.Position); storagePriority = StoragePriority.Unstored; return(true); // this takes us to capacity, and we haven't hit thing } } // if storable } // end list return(false); }
public Dialog_RenameDSU(CompDeepStorage cds) { this.cds = cds; curName = cds.parent.Label; }
static bool OverCapacity(Map map, Thing thing, ref StoragePriority storagePriority) { Utils.Warn(ShouldRemoveFromStorage, "LWM.DeepStorage: Over Capacity Called." + (map == null ? " Map is NULL (this is bad)." : (" Map: " + map)) + (thing == null? " Thing is NULL (this is bad).":(" Thing: " + thing.stackCount + thing))); if (!thing.Spawned) { return(false); } if (storagePriority == StoragePriority.Unstored) { return(false); } CompDeepStorage cds = (thing.Position.GetSlotGroup(map)?.parent as ThingWithComps)?.GetComp <CompDeepStorage>(); List <Thing> l; // What if it's a slotGroup put down after someone moved/destroyed a DSU? // Because we CAN still end up with more than one thing on the ground. // (Also, TODO: Other mods can possibly cause this. ...Hmmm...) if (cds == null) { l = map.thingGrid.ThingsListAt(thing.Position); for (int i = 0; i < l.Count; i++) { Utils.Mess(ShouldRemoveFromStorage, "LWM.DeepStorage: Not in DSU: looking at item " + ((l[i] != null)?l[i].ToString():"NULL ITEM")); if (l[i].def.EverStorable(false)) { if (thing == l[i]) // first thing is okay. { return(false); } Utils.Warn(ShouldRemoveFromStorage, "LWM.DeepStorage: " + thing.stackCount + thing + " is not in a DSU and there is already a thing at " + thing.Position); storagePriority = StoragePriority.Unstored; return(true); // anything else is over capactiy! } } return(false); // Should be difficult to get here? But apparently RoM - Arachnophobia does. } // TODO: This should really all be in CompDeepStorage: if (cds.limitingFactorForItem > 0f) { if (thing.GetStatValue(cds.stat) > cds.limitingFactorForItem) { Utils.Warn(ShouldRemoveFromStorage, "LWM.DeepStorage: " + thing.stackCount + thing + " is too heavy for DSU at " + thing.Position); storagePriority = StoragePriority.Unstored; return(true); } } float totalWeightStoredHere = 0f; //mass, or bulk, etc. var stacksStoredHere = 0; Utils.Mess(ShouldRemoveFromStorage, " Checking ThingListAt now..."); l = map.thingGrid.ThingsListAt(thing.Position); for (int i = 0; i < l.Count; i++) { Thing thingInStorage = l[i]; // TODO: Decide how to handle weight: if thing is stackable, do I want to take some out, if it goes over? if (thing == thingInStorage) { return(false); // it's here, and not over capacity yet! } if (thingInStorage.def.EverStorable(false)) // an "item" we care about { Utils.Mess(ShouldRemoveFromStorage, " Checking Item " + thingInStorage.stackCount + thingInStorage); stacksStoredHere++; if (cds.limitingTotalFactorForCell > 0f) { totalWeightStoredHere += thingInStorage.GetStatValue(cds.stat) * thingInStorage.stackCount; Utils.Mess(ShouldRemoveFromStorage, " total mass so far: " + totalWeightStoredHere + " / " + cds.limitingTotalFactorForCell); if (totalWeightStoredHere > cds.limitingTotalFactorForCell && stacksStoredHere >= cds.minNumberStacks) { Utils.Warn(ShouldRemoveFromStorage, "LWM.DeepStorage: " + thing.stackCount + thing + " is over weight capacity at " + thing.Position); storagePriority = StoragePriority.Unstored; return(true); // this takes us to capacity, and we haven't hit thing } } if (stacksStoredHere >= cds.maxNumberStacks) // breaks if minNumberStacks > maxNumberStacks. I'm okay with this { Utils.Warn(ShouldRemoveFromStorage, "LWM.DeepStorage: " + thing.stackCount + thing + " is over capacity at " + thing.Position); storagePriority = StoragePriority.Unstored; return(true); // this takes us to capacity, and we haven't hit thing } } // if storable } // end list return(false); }
static bool Prefix(Thing __instance) { if (Find.CameraDriver.CurrentZoom != CameraZoomRange.Closest) { return(false); } Building_Storage DSU = __instance as Building_Storage; if (DSU == null) { return(true); } CompDeepStorage cds = DSU.GetComp <CompDeepStorage>(); if (cds == null) { return(true); } if (cds.cdsProps.overlayType == LWM.DeepStorage.GuiOverlayType.Normal) { return(true); } if (cds.cdsProps.overlayType == GuiOverlayType.None) { return(false); } List <Thing> things; String s; if (cds.cdsProps.overlayType == GuiOverlayType.CountOfAllStacks) { // probably Armor Racks, Clothing Racks, Weapon Lockers etc... things = new List <Thing>(); foreach (IntVec3 c in DSU.AllSlotCellsList()) { things.AddRange(__instance.Map.thingGrid.ThingsListAtFast(c).FindAll(t => t.def.EverStorable(false))); } if (things.Count == 0) { if (cds.cdsProps.showContents) { return(false); // If it's empty, player will see! } s = "LWM_DS_Empty".Translate(); } else if (things.Count == 1) { s = 1.ToStringCached(); // Why not s="1";? You never know, someone may be playing in... } else if (AllSameType(things)) { s = "x" + things.Count.ToStringCached(); } else { s = "[ " + things.Count.ToStringCached() + " ]"; } GenMapUI.DrawThingLabel(GenMapUI.LabelDrawPosFor(__instance, 0f), s, GenMapUI.DefaultThingLabelColor); return(false); } if (cds.cdsProps.overlayType == GuiOverlayType.CountOfStacksPerCell) { // maybe Armor Racks, Clothing Racks? foreach (IntVec3 c in DSU.AllSlotCellsList()) { things = __instance.Map.thingGrid.ThingsListAtFast(c).FindAll(t => t.def.EverStorable(false)); if (things.Count == 0) { if (cds.cdsProps.showContents) { continue; // if it's empty, player will see! } s = "LWM_DS_Empty".Translate(); } else if (things.Count == 1) { s = 1.ToStringCached(); // ..a language that doesn't use arabic numerals? } else if (AllSameType(things)) { s = "x" + things.Count.ToStringCached(); } else { s = "[ " + things.Count.ToStringCached() + " ]"; } GenMapUI.DrawThingLabel(GenMapUI.LabelDrawPosFor(c), s, GenMapUI.DefaultThingLabelColor); } return(false); } if (cds.cdsProps.overlayType == GuiOverlayType.SumOfAllItems) { // probably food baskets, skips, etc... things = new List <Thing>(); foreach (IntVec3 c in DSU.slotGroup.CellsList) { things.AddRange(__instance.Map.thingGrid.ThingsListAtFast(c) .FindAll(t => t.def.EverStorable(false))); } if (things.Count == 0) { if (cds.cdsProps.showContents) { return(false); // if it's empty, player will see } s = "LWM_DS_Empty".Translate(); } else { int count = things[0].stackCount; bool allTheSame = true; for (int i = 1; i < things.Count; i++) { if (things[i].def != things[0].def) { allTheSame = false; } count += things[i].stackCount; } if (allTheSame) { s = count.ToStringCached(); } else { s = "[ " + count.ToStringCached() + " ]"; } } GenMapUI.DrawThingLabel(GenMapUI.LabelDrawPosFor(__instance, 0f), s, GenMapUI.DefaultThingLabelColor); return(false); } Log.Warning("LWM DeepStorage: could not find GuiOverlayType of " + cds.cdsProps.overlayType); return(true); }
public static void Postfix(Selector __instance) { if (__instance.NumSelected != 1) { return; } Thing t = __instance.SingleSelectedThing; if (t == null) { return; } if (!(t is ThingWithComps)) { return; } CompDeepStorage cds = t.TryGetComp <CompDeepStorage>(); if (cds == null) { return; } // Off to a good start; it's a DSU // Check to see if a tab is already open. var pane = (MainTabWindow_Inspect)MainButtonDefOf.Inspect.TabWindow; Type alreadyOpenTabType = pane.OpenTabType; if (alreadyOpenTabType != null) { var listOfTabs = t.GetInspectTabs(); foreach (var x in listOfTabs) { if (x.GetType() == alreadyOpenTabType) // Misses any subclassing? { return; // standard Selector behavior should kick in. } } } // If not, open ours! // TODO: ...make this happen for shelves, heck, any storage buildings? ITab tab = null; /* If there are no items stored, default intead to settings (preferably with note about being empty?) */ // If we find a stored item, open Contents tab: // TODO: Make storage settings tab show label if it's empty if (t.Spawned && t is IStoreSettingsParent && t is ISlotGroupParent) { foreach (IntVec3 c in ((ISlotGroupParent)t).GetSlotGroup().CellsList) { List <Thing> l = t.Map.thingGrid.ThingsListAt(c); foreach (Thing tmp in l) { if (tmp.def.EverStorable(false)) { goto EndLoop; // Seriously? C# doesn't have "break 2;"? } } } tab = t.GetInspectTabs().OfType <ITab_Storage>().First(); } EndLoop: if (tab == null) { tab = t.GetInspectTabs().OfType <ITab_DeepStorage_Inventory>().First(); } if (tab == null) { Log.Error("LWM Deep Storage object " + t + " does not have an inventory tab?"); return; } tab.OnOpen(); if (tab is ITab_DeepStorage_Inventory) { pane.OpenTabType = typeof(ITab_DeepStorage_Inventory); } else { pane.OpenTabType = typeof(ITab_Storage); } }
protected override void FillTab() { buildingStorage = this.SelThing as Building_Storage; // don't attach this to other things, 'k? List <Thing> storedItems; //TODO: set fonts ize, etc. Text.Font = GameFont.Small; // 10f border: Rect frame = new Rect(10f, 10f, this.size.x - 10, this.size.y - 10); GUI.BeginGroup(frame); Text.Font = GameFont.Small; GUI.color = Color.white; /******* Title *******/ float curY = 0f; Widgets.ListSeparator(ref curY, frame.width, labelKey.Translate() #if DEBUG + " (" + buildingStorage.ToString() + ")" // extra info for debugging #endif ); curY += 5f; /****************** Header: Show count of contents, mass, etc: ****************/ //TODO: handle each cell separately? string header, headerTooltip; CompDeepStorage cds = buildingStorage.GetComp <CompDeepStorage>(); if (cds != null) { storedItems = cds.getContentsHeader(out header, out headerTooltip); } else { storedItems = CompDeepStorage.genericContentsHeader(buildingStorage, out header, out headerTooltip); } Rect tmpRect = new Rect(8f, curY, frame.width - 16, Text.CalcHeight(header, frame.width - 16)); Widgets.Label(tmpRect, header); // TODO: tooltip. Not that it's anything but null now curY += (tmpRect.height); //todo? /************* ScrollView ************/ /************* (contents) ************/ storedItems = storedItems.OrderBy((Thing x) => x.def.defName). ThenByDescending((Thing x) => { QualityCategory c; x.TryGetQuality(out c); return((int)c); }). ThenByDescending((Thing x) => (x.HitPoints / x.MaxHitPoints)).ToList(); // outRect is the is the rectangle that is visible on the screen: Rect outRect = new Rect(0f, 10f + curY, frame.width, frame.height - curY - GenUI.ListSpacing - TopPadding); // viewRect is inside the ScrollView, so it starts at y=0f Rect viewRect = new Rect(0f, 0f, frame.width - 16f, this.scrollViewHeight);//TODO: scrollbars are slightly too far to the right // 16f ensures plenty of room for scrollbars. // scrollViewHeight is set at the end of this call (via layout?); it is the proper // size the next time through, so it all works out. Widgets.BeginScrollView(outRect, ref this.scrollPosition, viewRect, true); curY = 0f; // now inside ScrollView if (storedItems.Count < 1) { Widgets.Label(viewRect, "NoItemsAreStoredHere".Translate()); curY += 22; } string stringUpper = searchString.ToUpperInvariant(); List <Thing> itemToDraw = storedItems .Where(t => t.LabelNoCount .ToUpperInvariant() .Contains(stringUpper)).ToList(); GetIndexRangeFromScrollPosition(outRect.height, this.scrollPosition.y, out int from, out int to, GenUI.ListSpacing); to = to > itemToDraw.Count ? itemToDraw.Count : to; curY = from * GenUI.ListSpacing; for (int i = from; i < to; i++) { this.DrawThingRow(ref curY, viewRect.width, itemToDraw[i]); } if (Event.current.type == EventType.Layout) { this.scrollViewHeight = storedItems.Count * GenUI.ListSpacing + 25f; //25f buffer -- ?? } Widgets.EndScrollView(); searchString = Widgets.TextField( new Rect(0, outRect.yMax, outRect.width - GenUI.ScrollBarWidth, GenUI.ListSpacing) , searchString); GUI.EndGroup(); //TODO: this should get stored at top and set here. GUI.color = Color.white; //TODO: this should get stored at top and set here. // it should get set to whatever draw-row uses at top Text.Anchor = TextAnchor.UpperLeft; }
static bool Prefix(Thing __instance) { if (Find.CameraDriver.CurrentZoom != CameraZoomRange.Closest) { return(true); // maybe someone changes this? Who knows. } Building_Storage DSU = __instance as Building_Storage; if (DSU == null) { return(true); } CompDeepStorage cds = DSU.GetComp <CompDeepStorage>(); if (cds == null) { return(true); } if (cds.cdsProps.overlayType == LWM.DeepStorage.GuiOverlayType.Normal) { return(true); } if (cds.cdsProps.overlayType == GuiOverlayType.None) { return(false); } List <Thing> things; String s; if (cds.cdsProps.overlayType == GuiOverlayType.CountOfAllStacks) { // maybe Armor Racks, Clothing Racks, def Weapon Lockers etc... things = new List <Thing>(); foreach (IntVec3 c in DSU.AllSlotCellsList()) { things.AddRange(__instance.Map.thingGrid.ThingsListAtFast(c).FindAll(t => t.def.EverStorable(false))); } if (things.Count == 0) { if (cds.cdsProps.showContents) { return(false); // If it's empty, player will see! } s = "LWM_DS_Empty".Translate(); } else if (things.Count == 1) { s = 1.ToStringCached(); // Why not s="1";? You never know, someone may be playing in... } else if (AllSameType(things)) { s = "x" + things.Count.ToStringCached(); } else { s = "[ " + things.Count.ToStringCached() + " ]"; } GenMapUI.DrawThingLabel(GenMapUI.LabelDrawPosFor(__instance, 0f), s, GenMapUI.DefaultThingLabelColor); return(false); } if (cds.cdsProps.overlayType == GuiOverlayType.CountOfStacksPerCell) { // maybe Armor Racks, Clothing Racks? foreach (IntVec3 c in DSU.AllSlotCellsList()) { things = __instance.Map.thingGrid.ThingsListAtFast(c).FindAll(t => t.def.EverStorable(false)); if (things.Count == 0) { if (cds.cdsProps.showContents) { continue; // if it's empty, player will see! } s = "LWM_DS_Empty".Translate(); } else if (things.Count == 1) { s = 1.ToStringCached(); // ..a language that doesn't use arabic numerals? } else if (AllSameType(things)) { s = "x" + things.Count.ToStringCached(); } else { s = "[ " + things.Count.ToStringCached() + " ]"; } var l2 = GenMapUI.LabelDrawPosFor(c); // l2.x+=cds.x; // l2.y+=cds.y; l2.y += 10f; GenMapUI.DrawThingLabel(l2, s, GenMapUI.DefaultThingLabelColor); } return(false); } if (cds.cdsProps.overlayType == GuiOverlayType.SumOfAllItems) { // probably food baskets, skips, etc... things = new List <Thing>(); foreach (IntVec3 c in DSU.slotGroup.CellsList) { things.AddRange(__instance.Map.thingGrid.ThingsListAtFast(c) .FindAll(t => t.def.EverStorable(false))); } if (things.Count == 0) { if (cds.cdsProps.showContents) { return(false); // if it's empty, player will see } s = "LWM_DS_Empty".Translate(); } else { int count = things[0].stackCount; bool allTheSame = true; for (int i = 1; i < things.Count; i++) { if (things[i].def != things[0].def) { allTheSame = false; } count += things[i].stackCount; } if (allTheSame) { s = count.ToStringCached(); } else { s = "[ " + count.ToStringCached() + " ]"; } } GenMapUI.DrawThingLabel(GenMapUI.LabelDrawPosFor(__instance, 0f), s, GenMapUI.DefaultThingLabelColor); return(false); } if (cds.cdsProps.overlayType == GuiOverlayType.SumOfItemsPerCell) { // Big Shelves bool anyItems = false; foreach (IntVec3 c in DSU.AllSlotCellsList()) { bool itemsWithStackSizeOne = false; things = __instance.Map.thingGrid.ThingsListAtFast(c).FindAll(t => t.def.EverStorable(false)); if (things.Count > 0) { anyItems = true; int count = 0; for (int i = 0; i < things.Count; i++) { // Break logic if there is anything with a stackLimit of 1 // show instead the count of stacks: if (itemsWithStackSizeOne || things[i].def.stackLimit == 1) { itemsWithStackSizeOne = true; if (things.Count == 1) { s = 1.ToStringCached(); // ..a language that doesn't use arabic numerals? } else if (AllSameType(things)) { s = "x" + things.Count.ToStringCached(); } else { s = "[ " + things.Count.ToStringCached() + " ]"; } var l = GenMapUI.LabelDrawPosFor(c); l.y += 10f; GenMapUI.DrawThingLabel(l, s, GenMapUI.DefaultThingLabelColor); goto WhyDoesCSharpNotHaveBreakTwo; } else { count += things[i].stackCount; } } // end list of things. if (AllSameType(things)) { s = count.ToStringCached(); } else { s = "[ " + count.ToStringCached() + " ]"; } var l2 = GenMapUI.LabelDrawPosFor(c); l2.y += 10f; GenMapUI.DrawThingLabel(l2, s, GenMapUI.DefaultThingLabelColor); } // if count > 0 WhyDoesCSharpNotHaveBreakTwo :; } // foreach cell if (!anyItems && !cds.cdsProps.showContents) // there are no items, but no way to see that. { s = "LWM_DS_Empty".Translate(); GenMapUI.DrawThingLabel(GenMapUI.LabelDrawPosFor(__instance, 0f), s, GenMapUI.DefaultThingLabelColor); } return(false); } Log.Warning("LWM DeepStorage: could not find GuiOverlayType of " + cds.cdsProps.overlayType); return(true); }
protected override void FillTab() { var storageBuilding = SelThing as Building_Storage; // don't attach this to other things, 'k? List <Thing> storedItems; //TODO: set fonts ize, etc. Text.Font = GameFont.Small; // 10f border: var frame = new Rect(10f, 10f, size.x - 10, size.y - 10); GUI.BeginGroup(frame); Text.Font = GameFont.Small; GUI.color = Color.white; /******* Title *******/ var curY = 0f; Widgets.ListSeparator(ref curY, frame.width, labelKey.Translate() #if DEBUG + " (" + storageBuilding.ToString() + ")" // extra info for debugging #endif ); curY += 5f; /****************** Header: Show count of contents, mass, etc: ****************/ //TODO: handle each cell separately? string header, headerTooltip; var cds = storageBuilding.GetComp <CompDeepStorage>(); if (cds != null) { storedItems = cds.getContentsHeader(out header, out headerTooltip); } else { storedItems = CompDeepStorage.genericContentsHeader(storageBuilding, out header, out headerTooltip); } var tmpRect = new Rect(8f, curY, frame.width - 16, Text.CalcHeight(header, frame.width - 16)); Widgets.Label(tmpRect, header); // TODO: tooltip. Not that it's anything but null now curY += tmpRect.height; //todo? /************* ScrollView ************/ /************* (contents) ************/ storedItems = storedItems.OrderBy(x => x.def.defName).ThenByDescending(x => { QualityCategory c; x.TryGetQuality(out c); return((int)c); }).ThenByDescending(x => x.HitPoints / x.MaxHitPoints).ToList(); // outRect is the is the rectangle that is visible on the screen: var outRect = new Rect(0f, 10f + curY, frame.width, frame.height - curY); // viewRect is inside the ScrollView, so it starts at y=0f var viewRect = new Rect(0f, 0f, frame.width - 16f, scrollViewHeight); //TODO: scrollbars are slightly too far to the right // 16f ensures plenty of room for scrollbars. // scrollViewHeight is set at the end of this call (via layout?); it is the proper // size the next time through, so it all works out. Widgets.BeginScrollView(outRect, ref scrollPosition, viewRect); curY = 0f; // now inside ScrollView if (storedItems.Count < 1) { Widgets.Label(viewRect, "NoItemsAreStoredHere".Translate()); curY += 22; } for (var i = 0; i < storedItems.Count; i++) { DrawThingRow(ref curY, viewRect.width, storedItems[i]); } if (Event.current.type == EventType.Layout) { scrollViewHeight = curY + 25f; //25f buffer -- ?? } Widgets.EndScrollView(); GUI.EndGroup(); //TODO: this should get stored at top and set here. GUI.color = Color.white; //TODO: this should get stored at top and set here. // it should get set to whatever draw-row uses at top Text.Anchor = TextAnchor.UpperLeft; }
// LWM rewrote most of this method to meet their implementation of CompDeepStorage private void DisplayHeaderInfo(ref float curY, float width, Building_Storage building, int numCells, List <Thing> itemsList) { // Header information regardless of what the storage building is: Rect rect = new Rect(0f, curY, width, 22f); // TODO: Add hooks for other mods: // E.g., StockpileForDisaster has a nice little checkbox that shows whether // pawns can freely take from the unit, or whether restrictions are in effect CompDeepStorage cds = building.GetComp <CompDeepStorage>(); if (cds == null) { return; // what are we even doing here, mmm? In a vanilla shelf, probably! } bool flagUseStackInsteadOfItem = false; // "3/4 Items" vs "3/4 Stacks" float itemsTotalMass = 0; // or Bulk for CE ;p for (int i = 0; i < itemsList.Count; i++) { itemsTotalMass += itemsList[i].GetStatValue(cds.stat, true) * (float)itemsList[i].stackCount; if (itemsList[i].def.stackLimit > 1) { flagUseStackInsteadOfItem = true; } } if (cds.limitingTotalFactorForCell > 0f) { string tmpLabel = "LWM.ContentsHeaderItemsMass"; if (flagUseStackInsteadOfItem) { tmpLabel = "LWM.ContentsHeaderStacksMass"; } Widgets.Label(rect, tmpLabel.Translate(itemsList.Count, cds.maxNumberStacks * numCells, cds.stat.ToString().ToLower(), itemsTotalMass.ToString("0.##"), (cds.limitingTotalFactorForCell * numCells).ToString("0.##"))); } else { string tmpLabel = "LWM.ContentsHeaderItems"; if (flagUseStackInsteadOfItem) { tmpLabel = "LWM.ContentsHeaderStacks"; } Widgets.Label(rect, tmpLabel.Translate(itemsList.Count, cds.maxNumberStacks * numCells, cds.stat.ToString().ToLower(), itemsTotalMass.ToString("0.##"))); } curY += 22f; /* Limiting factor for Item: what's too damn big */ if (cds.limitingFactorForItem > 0f) { rect = new Rect(0f, curY, width, 22f); Widgets.Label(rect, "LWM.ContentsHeaderMaxSize".Translate( cds.stat.ToString().ToLower(), cds.limitingFactorForItem.ToString("0.##") )); curY += 22f; } /* Pawn reservations. I hope this cuts down on questions in the Steam thread */ List <Pawn> pwns = building.Map.mapPawns.SpawnedPawnsInFaction(Faction.OfPlayer); if (pwns.Count > 0) { listOfReservingPawns.Clear(); List <IntVec3> buildingCells = building.AllSlotCellsList(); for (int i = 0; i < buildingCells.Count; i++) { Pawn p = building.Map.reservationManager.FirstRespectedReserver(buildingCells[i], pwns[0]); if (p != null) { listOfReservingPawns.Add(p.ToString()); } } if (listOfReservingPawns.Count > 0) { rect = new Rect(0f, curY, width, 22f); if (listOfReservingPawns.Count == 1) { Widgets.Label(rect, "LWM.ContentsHeaderPawnUsing".Translate(listOfReservingPawns[0])); } else { Widgets.Label(rect, "LWM.ContentsHeaderPawnsUsing".Translate( String.Join(", ", listOfReservingPawns.ToArray()))); } curY += 22f; } } // end checking pawn reservations } // end Header for ITab