private void RockTypesFromUnder() { // Try to add all the rock types found in the map if (!checkedRocksUnder && rockTypesUnder.NullOrEmpty()) { foreach (IntVec3 c in this.OccupiedRect()) { // What type of terrain are we over? TerrainDef td = c.GetTerrain(Map); // If this is a valid rock type, add it to the list if (QuarryUtility.IsValidQuarryRock(td, out QuarryRockType rockType, out string key) && !rocksUnder.Contains(rockType) && !rockTypesUnder.Contains(key)) { // Log.Message($"{td} rock type {rockType.rockDef} blocks: {rockType.blockDef} with key {key}"); rocksUnder.Add(rockType); rockTypesUnder.Add(key); } } checkedRocksUnder = true; } else { for (int i = 0; i < rockTypesUnder.Count; i++) { if (QuarrySettings.quarryableStone.TryGetValue(rockTypesUnder[i], out QuarryRockType rockType)) { rocksUnder.Add(rockType); } } } }
private void ProcessBoolGrid() { foreach (IntVec3 c in map.AllCells) { boolGrid.Set(c, QuarryUtility.IsValidQuarryTerrain(map.terrainGrid.TerrainAt(c))); } Drawer.SetDirty(); }
private void BuildDictionary() { if (QuarrySettings.oreDictionary == null) { OreDictionary.Build(); } if (QuarrySettings.quarryableStone == null) { QuarryUtility.BuildStoneDict(); } QuarryDefOf.QRY_ReclaimedSoil.fertility = QuarrySettings.reclaimedSoilFertility; }
public override void SpawnSetup(Map map, bool respawningAfterLoad) { base.SpawnSetup(map, respawningAfterLoad); facilityComp = GetComp <CompAffectedByFacilities>(); if (firstSpawn) { // Set the initial quarry health quarryPercent = 1f; CellRect rect = this.OccupiedRect(); // Remove this area from the quarry grid. Quarries can never be built here again map.GetComponent <QuarryGrid>().RemoveFromGrid(rect); foreach (IntVec3 c in rect) { // What type of terrain are we over? string rockType = c.GetTerrain(Map).label.Split(' ').Last().CapitalizeFirst(); // If this is a valid rock type, add it to the list if (QuarryUtility.IsValidQuarryRock(rockType)) { rockTypesUnder.Add(rockType); } // Change the terrain here to be quarried stone if (rect.ContractedBy(WallThickness).Contains(c)) { Map.terrainGrid.SetTerrain(c, QuarryDefOf.QRY_QuarriedGround); } else { Map.terrainGrid.SetTerrain(c, QuarryDefOf.QRY_QuarriedGroundWall); } } // Now that all the cells have been processed, create ThingDef lists MakeThingDefListsFrom(RockTypesUnder); // Spawn filth for the quarry foreach (IntVec3 c in rect) { SpawnFilth(c); } // Change the ground back to normal quarried stone where the ladders are // This is to negate the speed decrease and encourages pawns to use the ladders foreach (IntVec3 offset in LadderOffsets) { Map.terrainGrid.SetTerrain(Position + offset.RotatedBy(Rotation), QuarryDefOf.QRY_QuarriedGround); } } }
private void MakeThingDefListsFrom(List <string> stringList) { chunksUnder = new List <ThingDef>(); blocksUnder = new List <ThingDef>(); foreach (string str in stringList) { if (QuarryUtility.IsValidQuarryChunk(str, out ThingDef chunk)) { chunksUnder.Add(chunk); } if (QuarryUtility.IsValidQuarryBlocks(str, out ThingDef blocks)) { blocksUnder.Add(blocks); } } }
private List <string> RockTypesFromMap() { // Try to add all the rock types found in the map List <string> list = new List <string>(); List <string> tempRockTypesUnder = Find.World.NaturalRockTypesIn(Map.Tile).Select(r => r.LabelCap).ToList(); foreach (string str in tempRockTypesUnder) { if (QuarryUtility.IsValidQuarryRock(str)) { list.Add(str); } } // This will cause an error if there still isn't a list, so make a new one using known rocks if (list.Count <= 0) { Log.Warning("Quarry:: No valid rock types were found in the map. Building list using vanilla rocks."); list = new List <string>() { "Sandstone", "Limestone", "Granite", "Marble", "Slate" }; } return(list); }
public override void DoSettingsWindowContents(Rect rect) { Listing_Standard list = new Listing_Standard() { ColumnWidth = rect.width }; Rect topRect = rect.TopPart(0.25f); Rect bottomRect = rect.BottomPart(0.75f); Rect fullRect = list.GetRect(Text.LineHeight).ContractedBy(4); Rect leftRect = fullRect.LeftHalf().Rounded(); Rect rightRect = fullRect.RightHalf().Rounded(); list.Begin(rect); list.QuarryHealthSetting(); Listing_Standard listtop = list.BeginSection(topRect.height, true); { listtop.ColumnWidth = rect.width / 2; listtop.CheckboxLabeled(Static.LetterSent, ref QuarrySettings.letterSent, Static.ToolTipLetter); listtop.CheckboxLabeled(Static.AllowRottable, ref QuarrySettings.allowRottable, Static.ToolTipAllowRottable); listtop.NewColumn(); listtop.LabeledScrollbarSetting("QRY_SettingsJunkChance".Translate(QuarrySettings.junkChance), ref QuarrySettings.junkChance, Static.ToolTipJunkChance); listtop.LabeledScrollbarSetting("QRY_SettingsChunkChance".Translate(QuarrySettings.chunkChance), ref QuarrySettings.chunkChance, Static.ToolTipChunkChance); listtop.LabeledScrollbarSetting("QRY_SettingsResourceModifier".Translate(QuarrySettings.resourceModifer * 100), ref QuarrySettings.resourceModifer, Static.ToolTipResourceModifier); } list.EndSection(listtop); /* * Listing_Standard listbottom = list.BeginSection(bottomRect.height, true); * { * * } * list.EndSection(listbottom); */ list.End(); { Rect DictInterfaceRect = bottomRect.TopPart(0.25f).Rounded(); { Rect labelRect = DictInterfaceRect.TopPart(0.75f).Rounded(); Text.Font = GameFont.Medium; Text.Anchor = TextAnchor.MiddleCenter; Widgets.Label(labelRect, Static.LabelDictionary); Text.Font = GameFont.Small; Text.Anchor = TextAnchor.UpperLeft; } { Rect buttonsRect = DictInterfaceRect.BottomPart(0.25f).Rounded(); Rect addRect = buttonsRect.LeftThird(); Rect rmvRect = buttonsRect.MiddleThird(); Rect resRect = buttonsRect.RightThird(); // Add an entry to the dictionary if (Widgets.ButtonText(addRect, Static.LabelAddThing)) { List <FloatMenuOption> thingList = new List <FloatMenuOption>(); foreach (ThingDef current in from t in QuarryUtility.PossibleThingDefs() orderby t.label select t) { bool skip = false; for (int i = 0; i < QuarrySettings.oreDictionary.Count; i++) { if (QuarrySettings.oreDictionary[i].thingDef == current) { skip = true; break; } } ; if (skip) { continue; } thingList.Add(new FloatMenuOption(current.LabelCap, delegate { QuarrySettings.oreDictionary.Add(new ThingCountExposable(current, 1)); })); } FloatMenu menu = new FloatMenu(thingList); Find.WindowStack.Add(menu); } // Remove an entry from the dictionary if (Widgets.ButtonText(rmvRect, Static.LabelRemoveThing) && QuarrySettings.oreDictionary.Count >= 2) { List <FloatMenuOption> thingList = new List <FloatMenuOption>(); foreach (ThingCountExposable current in from t in QuarrySettings.oreDictionary orderby t.thingDef.label select t) { ThingDef localTd = current.thingDef; thingList.Add(new FloatMenuOption(localTd.LabelCap, delegate { for (int i = 0; i < QuarrySettings.oreDictionary.Count; i++) { if (QuarrySettings.oreDictionary[i].thingDef == localTd) { QuarrySettings.oreDictionary.Remove(QuarrySettings.oreDictionary[i]); break; } } ; })); } FloatMenu menu = new FloatMenu(thingList); Find.WindowStack.Add(menu); } // Reset the dictionary if (Widgets.ButtonText(resRect, Static.LabelResetList)) { OreDictionary.Build(); } } { Rect listRect = bottomRect.BottomPart(0.75f).Rounded(); Rect cRect = listRect.ContractedBy(10f); Rect position = listRect; Rect outRect = new Rect(0f, 0f, position.width, position.height); Rect viewRect = new Rect(0f, 0f, position.width - 16f, scrollViewHeight); float num = 0f; List <ThingCountExposable> dict = new List <ThingCountExposable>(QuarrySettings.oreDictionary); GUI.BeginGroup(position); Widgets.BeginScrollView(outRect, ref scrollPosition, viewRect, true); foreach (var tc in dict.Select((value, index) => new { index, value })) { Rect entryRect = new Rect(0f, num, viewRect.width, 32); Rect iconRect = entryRect.LeftPartPixels(32); Rect labelRect = new Rect(entryRect.LeftThird().x + 33f, entryRect.y, entryRect.LeftThird().width - 33f, entryRect.height); Rect texEntryRect = new Rect(entryRect.LeftHalf().RightPartPixels(103).x, entryRect.y, 60f, entryRect.height); Rect pctRect = new Rect(entryRect.LeftHalf().RightPartPixels(41).x, entryRect.y, 40f, entryRect.height); Rect sliderRect = new Rect(entryRect.RightHalf().x, entryRect.y, entryRect.RightHalf().width, entryRect.height); Widgets.ThingIcon(iconRect, tc.value.thingDef); Widgets.Label(labelRect, tc.value.thingDef.LabelCap); Widgets.Label(pctRect, $"{QuarrySettings.oreDictionary.WeightAsPercentageOf(tc.value.count).ToStringDecimal()}%"); int val = tc.value.count; string nullString = null; Widgets.TextFieldNumeric( texEntryRect, ref QuarrySettings.oreDictionary[tc.index].count, ref nullString, 0, OreDictionary.MaxWeight); val = Widgets.HorizontalSlider( sliderRect, QuarrySettings.oreDictionary[tc.index].count, 0f, OreDictionary.MaxWeight, true ).RoundToAsInt(1); if (val != QuarrySettings.oreDictionary[tc.index].count) { QuarrySettings.oreDictionary[tc.index].count = val; } if (Mouse.IsOver(entryRect)) { Widgets.DrawHighlight(entryRect); } TooltipHandler.TipRegion(entryRect.LeftThird(), tc.value.thingDef.description); num += 32f; scrollViewHeight = num; } Widgets.EndScrollView(); GUI.EndGroup(); } } }
public static void BuildStoneDict() { QuarrySettings.quarryableStone = new Dictionary <string, QuarryRockType>(); List <string> processed = new List <string>(); List <TerrainDef> terrainDefs = DefDatabase <TerrainDef> .AllDefsListForReading; List <ThingDef> rockDefs = DefDatabase <ThingDef> .AllDefsListForReading.FindAll(x => x.building?.mineableThing != null /*&& x.building.mineableThing.defName.Contains("Chunk")*/); List <ThingDef> chunkDefs = DefDatabase <ThingDef> .AllDefsListForReading.FindAll(x => x.defName.Contains("Chunk") && rockDefs.Any(y => y.building.mineableThing == x)); List <ThingDef> blockDefs = DefDatabase <ThingDef> .AllDefsListForReading.FindAll(x => x.defName.Contains("Blocks")); /* * Log.Message($"Quarry: Checking\n" + * $"{blockDefs.Count} Blocks {((List<string>)blockDefs.Select(r => r.LabelCap)).ToCommaList()}" + * $"\n\n{chunkDefs.Count} Chunks {((List<string>)chunkDefs.Select(r => r.LabelCap)).ToCommaList()}" + * $"\n\n{rockDefs.Count} Rocks {((List<string>)rockDefs.Select(r => r.LabelCap)).ToCommaList()}" + * $"\n\n{terrainDefs.Count} TerrainDefs {((List<string>)terrainDefs.Select(r => r.LabelCap)).ToCommaList()}"); */ List <QuarryableStoneDef> modDefs = DefDatabase <QuarryableStoneDef> .AllDefsListForReading; // Log.Message($"Quarry: Checking {rockDefs.Count} rockDefs"); foreach (var rockDef in rockDefs) { if (rockDef.building.naturalTerrain == null || QuarrySettings.quarryableStone.Values.Any(x => x.rockDef == rockDef)) { continue; } ThingDef chunkDef = rockDef.building.mineableThing; TerrainDef terrainNatural = rockDef.building.naturalTerrain; TerrainDef terrainLeave = rockDef.building.leaveTerrain; TerrainDef terrainSmoothed = terrainNatural?.smoothedTerrain ?? null; ThingDef blockDef = blockDefs.Find(x => x.label.Contains(rockDef.label)) ?? null; QuarrySettings.quarryableStone.Add(rockDef.LabelCap, new QuarryRockType(rockDef, chunkDef, blockDef)); // Log.Message($"Quarry:: RockDef New: {rockDef.LabelCap}:: rockDef: {rockDef}, chunkDef: {chunkDef}, blockDef: {blockDef}"); if (!processed.Contains(rockDef.LabelCap)) { processed.Add(rockDef.LabelCap); } } // Log.Message($"Quarry: Checking {modDefs.Count} QuarryableStoneDefs"); foreach (var modDef in modDefs) { string rockType = QuarryUtility.RockType(modDef.terrainTag); ThingDef rockDef = modDef.rockDef ?? rockDefs.Find(x => x.defName.Contains(rockType)); // Log.Message($"Quarry: Checking modDef: {modDef} "); ThingDef chunkDef = modDef.chunkDef ?? chunkDefs.Find(x => x.defName.Contains(rockType)); ThingDef blockDef = modDef.blockDef ?? blockDefs.Find(x => x.defName.Contains(rockType)); if (chunkDef == null && rockDef != null) { chunkDef = rockDef.building.mineableThing; } if (chunkDef != null) { if (!modDef.terrainDefs.NullOrEmpty() && QuarrySettings.quarryableStone.First(x => x.Value.chunkDef == chunkDef).Value is QuarryRockType quarryRock) { quarryRock.terrainDefs.AddRange(modDef.terrainDefs); // Log.Message($"Quarry:: QuarryableStoneDef Updated: {rockType}:: rockDef: {rockDef}, chunkDef: {chunkDef}, blockDef: {blockDef}"); } else { QuarrySettings.quarryableStone.Add(rockDef.LabelCap, new QuarryRockType(rockDef, chunkDef, blockDef)); // Log.Message($"Quarry:: QuarryableStoneDef New: {rockType}:: rockDef: {rockDef}, chunkDef: {chunkDef}, blockDef: {blockDef}"); } if (!processed.Contains(rockDef.LabelCap)) { processed.Add(rockDef.LabelCap); } } } // Log.Message($"Quarry: Checking {terrainDefs.Count} terrainDefs"); foreach (var terrainDef in terrainDefs) { if (QuarrySettings.quarryableStone.Values.Any(x => x.terrainDefs.Contains(terrainDef))) { continue; } string rockType = QuarryUtility.RockType(terrainDef.defName); ThingDef rockDef = rockDefs.Find(x => x.defName.Contains(rockType)); if (rockDef == null || rockType == "Sand") { continue; } // Log.Message($"Quarry: Checking terrainDef: {item} "); ThingDef chunkDef = chunkDefs.Find(x => x.defName.Contains(rockType)); ThingDef blockDef = blockDefs.Find(x => x.defName.Contains(rockType)); if (chunkDef == null && rockDef != null && ((rockDef.building.naturalTerrain != null && rockDef.building.naturalTerrain == terrainDef) || (rockDef.building.leaveTerrain != null && rockDef.building.leaveTerrain == terrainDef))) { chunkDef = rockDef.building.mineableThing; } if (chunkDef != null) { if (QuarrySettings.quarryableStone.First(x => x.Value.chunkDef == chunkDef).Value is QuarryRockType quarryRock) { quarryRock.terrainDefs.Add(terrainDef); // Log.Message($"Quarry:: TerrainDef Updated: {terrainDef}:: rockDef: {rockDef}, chunkDef: {chunkDef}, blockDef: {blockDef}"); } else { QuarrySettings.quarryableStone.Add(rockDef.LabelCap, new QuarryRockType(rockDef, chunkDef, blockDef)); // Log.Message($"Quarry:: TerrainDef New: {terrainDef}:: rockDef: {rockDef}, chunkDef: {chunkDef}, blockDef: {blockDef}"); } if (!processed.Contains(rockDef.LabelCap)) { processed.Add(rockDef.LabelCap); } } } Log.Message($"Quarry:: Total {processed.Count} quarryable terrain found, processed: {processed.ToCommaList()}" + (modDefs.Count > 0 ? $"\n{modDefs.Count} QuarryableStoneDef's found" : "")); }
public override void SpawnSetup(Map map, bool respawningAfterLoad) { base.SpawnSetup(map, respawningAfterLoad); facilityComp = GetComp <CompAffectedByFacilities>(); if (firstSpawn) { // Set the initial quarry health quarryPercent = 1f; CellRect rect = this.OccupiedRect(); // Remove this area from the quarry grid. Quarries can never be built here again // map.GetComponent<QuarryGrid>().RemoveFromGrid(rect); foreach (IntVec3 c in rect) { // What type of terrain are we over? TerrainDef td = c.GetTerrain(Map); // Original method, problem here is that mods that use prefixes like Alpha Biomes "AB_" trigger the split and only pass the prefix, not the defname // string rockType = td.defName.Split('_').First(); // this seems like a better method, mods with prfixes are a little easier to handle stone from string rockType = td.defName; if (rockType.EndsWith("_Rough")) { rockType = rockType.Replace("_Rough", ""); } else if (rockType.EndsWith("_RoughHewn")) { rockType = rockType.Replace("_RoughHewn", ""); } else if (rockType.EndsWith("_Smooth")) { rockType = rockType.Replace("_Smooth", ""); } else { continue; } // crappy alpha biomes compatability, gotta be a better method if (rockType.StartsWith("GU_")) { rockType = rockType.Replace("GU_", ""); } if (rockType.StartsWith("AB_")) { rockType = rockType.Replace("AB_", ""); } // If this is a valid rock type, add it to the list if (QuarryUtility.IsValidQuarryRock(rockType)) { rockTypesUnder.Add(rockType); } // Change the terrain here to be quarried stone if (rect.ContractedBy(WallThickness).Contains(c)) { Map.terrainGrid.SetTerrain(c, QuarryDefOf.QRY_QuarriedGround); } else { Map.terrainGrid.SetTerrain(c, QuarryDefOf.QRY_QuarriedGroundWall); } } // Now that all the cells have been processed, create ThingDef lists MakeThingDefListsFrom(RockTypesUnder); // Spawn filth for the quarry foreach (IntVec3 c in rect) { SpawnFilth(c); } // Change the ground back to normal quarried stone where the ladders are // This is to negate the speed decrease and encourages pawns to use the ladders foreach (IntVec3 offset in LadderOffsets) { Map.terrainGrid.SetTerrain(Position + offset.RotatedBy(Rotation), QuarryDefOf.QRY_QuarriedGround); } } }
public override void DoSettingsWindowContents(Rect rect) { Listing_Standard list = new Listing_Standard() { ColumnWidth = rect.width }; list.Begin(rect); list.Gap(10); { Rect fullRect = list.GetRect(Text.LineHeight); Rect leftRect = fullRect.LeftHalf().Rounded(); Rect rightRect = fullRect.RightHalf().Rounded(); if (QuarrySettings.quarryMaxHealth <= 10000) { Widgets.Label(leftRect, "QRY_DepletionLabel".Translate(QuarrySettings.quarryMaxHealth.ToString("N0"))); } else { Widgets.Label(leftRect, "QRY_DepletionLabel".Translate("Infinite")); } //Increment timer value by -100 (button). if (Widgets.ButtonText(new Rect(rightRect.xMin, rightRect.y, rightRect.height, rightRect.height), "-", true, false, true)) { if (QuarrySettings.quarryMaxHealth >= 200) { QuarrySettings.quarryMaxHealth -= 100; } } QuarrySettings.quarryMaxHealth = Widgets.HorizontalSlider( new Rect(rightRect.xMin + rightRect.height + 10f, rightRect.y, rightRect.width - ((rightRect.height * 2) + 20f), rightRect.height), QuarrySettings.quarryMaxHealth, 100f, 10100f, true).RoundToAsInt(100); //Increment timer value by +100 (button). if (Widgets.ButtonText(new Rect(rightRect.xMax - rightRect.height, rightRect.y, rightRect.height, rightRect.height), "+", true, false, true)) { if (QuarrySettings.quarryMaxHealth < 10100) { QuarrySettings.quarryMaxHealth += 100; } } list.Gap(25); { Rect letterRect = list.GetRect(Text.LineHeight).LeftHalf().Rounded(); Widgets.CheckboxLabeled(letterRect, Static.LetterSent, ref QuarrySettings.letterSent); if (Mouse.IsOver(letterRect)) { Widgets.DrawHighlight(letterRect); } TooltipHandler.TipRegion(letterRect, Static.ToolTipLetter); } list.Gap(25); { Rect junkRect = list.GetRect(Text.LineHeight).LeftHalf().Rounded(); Rect junkSliderOffset = junkRect.RightHalf().Rounded().RightPartPixels(200); Widgets.Label(junkRect, "QRY_SettingsJunkChance".Translate(QuarrySettings.junkChance)); QuarrySettings.junkChance = Widgets.HorizontalSlider( junkSliderOffset, QuarrySettings.junkChance, 0f, 100f, true).RoundToAsInt(5); if (Mouse.IsOver(junkRect)) { Widgets.DrawHighlight(junkRect); } TooltipHandler.TipRegion(junkRect, Static.ToolTipJunkChance); } list.Gap(25); { Rect chunkRect = list.GetRect(Text.LineHeight).LeftHalf().Rounded(); Rect chunkSliderOffset = chunkRect.RightHalf().Rounded().RightPartPixels(200); Widgets.Label(chunkRect, "QRY_SettingsChunkChance".Translate(QuarrySettings.chunkChance)); QuarrySettings.chunkChance = Widgets.HorizontalSlider( chunkSliderOffset, QuarrySettings.chunkChance, 0f, 100f, true).RoundToAsInt(5); if (Mouse.IsOver(chunkRect)) { Widgets.DrawHighlight(chunkRect); } TooltipHandler.TipRegion(chunkRect, Static.ToolTipChunkChance); } list.Gap(15); { Rect labelRect = list.GetRect(32).Rounded(); Text.Font = GameFont.Medium; Text.Anchor = TextAnchor.MiddleCenter; Widgets.Label(labelRect, Static.LabelDictionary); Text.Font = GameFont.Small; Text.Anchor = TextAnchor.UpperLeft; } list.Gap(1); { Rect buttonsRect = list.GetRect(Text.LineHeight).Rounded(); Rect addRect = buttonsRect.LeftThird(); Rect rmvRect = buttonsRect.MiddleThird(); Rect resRect = buttonsRect.RightThird(); // Add an entry to the dictionary if (Widgets.ButtonText(addRect, Static.LabelAddThing)) { List <FloatMenuOption> thingList = new List <FloatMenuOption>(); foreach (ThingDef current in from t in QuarryUtility.PossibleThingDefs() orderby t.label select t) { bool skip = false; for (int i = 0; i < QuarrySettings.oreDictionary.Count; i++) { if (QuarrySettings.oreDictionary[i].thingDef == current) { skip = true; break; } } ; if (skip) { continue; } thingList.Add(new FloatMenuOption(current.LabelCap, delegate { QuarrySettings.oreDictionary.Add(new ThingCountExposable(current, 1)); })); } FloatMenu menu = new FloatMenu(thingList); Find.WindowStack.Add(menu); } // Remove an entry from the dictionary if (Widgets.ButtonText(rmvRect, Static.LabelRemoveThing) && QuarrySettings.oreDictionary.Count >= 2) { List <FloatMenuOption> thingList = new List <FloatMenuOption>(); foreach (ThingCountExposable current in from t in QuarrySettings.oreDictionary orderby t.thingDef.label select t) { ThingDef localTd = current.thingDef; thingList.Add(new FloatMenuOption(localTd.LabelCap, delegate { for (int i = 0; i < QuarrySettings.oreDictionary.Count; i++) { if (QuarrySettings.oreDictionary[i].thingDef == localTd) { QuarrySettings.oreDictionary.Remove(QuarrySettings.oreDictionary[i]); break; } } ; })); } FloatMenu menu = new FloatMenu(thingList); Find.WindowStack.Add(menu); } // Reset the dictionary if (Widgets.ButtonText(resRect, Static.LabelResetList)) { OreDictionary.Build(); } } list.Gap(5); { Rect listRect = list.GetRect(300f).Rounded(); Rect cRect = listRect.ContractedBy(10f); Rect position = new Rect(cRect.x, cRect.y, cRect.width, cRect.height); Rect outRect = new Rect(0f, 0f, position.width, position.height); Rect viewRect = new Rect(0f, 0f, position.width - 16f, scrollViewHeight); float num = 0f; List <ThingCountExposable> dict = new List <ThingCountExposable>(QuarrySettings.oreDictionary); GUI.BeginGroup(position); Widgets.BeginScrollView(outRect, ref scrollPosition, viewRect, true); foreach (var tc in dict.Select((value, index) => new { index, value })) { Rect entryRect = new Rect(0f, num, viewRect.width, 32); Rect iconRect = entryRect.LeftPartPixels(32); Rect labelRect = new Rect(entryRect.LeftThird().x + 33f, entryRect.y, entryRect.LeftThird().width - 33f, entryRect.height); Rect texEntryRect = new Rect(entryRect.LeftHalf().RightPartPixels(103).x, entryRect.y, 60f, entryRect.height); Rect pctRect = new Rect(entryRect.LeftHalf().RightPartPixels(41).x, entryRect.y, 40f, entryRect.height); Rect sliderRect = new Rect(entryRect.RightHalf().x, entryRect.y, entryRect.RightHalf().width, entryRect.height); Widgets.ThingIcon(iconRect, tc.value.thingDef); Widgets.Label(labelRect, tc.value.thingDef.LabelCap); Widgets.Label(pctRect, $"{QuarrySettings.oreDictionary.WeightAsPercentageOf(tc.value.count).ToStringDecimal()}%"); int val = tc.value.count; string nullString = null; Widgets.TextFieldNumeric( texEntryRect, ref QuarrySettings.oreDictionary[tc.index].count, ref nullString, 0, OreDictionary.MaxWeight); val = Widgets.HorizontalSlider( sliderRect, QuarrySettings.oreDictionary[tc.index].count, 0f, OreDictionary.MaxWeight, true ).RoundToAsInt(1); if (val != QuarrySettings.oreDictionary[tc.index].count) { QuarrySettings.oreDictionary[tc.index].count = val; } if (Mouse.IsOver(entryRect)) { Widgets.DrawHighlight(entryRect); } TooltipHandler.TipRegion(entryRect.LeftThird(), tc.value.thingDef.description); num += 32f; scrollViewHeight = num; } Widgets.EndScrollView(); GUI.EndGroup(); } list.End(); } }