public static void Scan_Materials(InventorySection section, ref HashSet <Material> materials) { if (!materials.Contains(new Material("Mora", 0))) { materials.Add(new Material("Mora", ScanMora())); } int scrollCount = 0; Material material = new Material(null, 0); Material previousMaterial = new Material(null, -1); List <Rectangle> rectangles; int page = 0; // Keep scanning while not repeating any items names while (true) { int rows, cols; // Find all items on the screen (rectangles, cols, rows) = GetPageOfItems(section, page); // Remove last row. Sometimes the bottom of a page of items is caught which results // in a faded quantity that can't be parsed. Removing slightly increases the number of pages that // need to be scrolled but it's fine. var r = rectangles.Take(rectangles.Count() - cols).ToList(); foreach (var rectangle in r) { // Select Material Navigation.SetCursorPos(Navigation.GetPosition().Left + rectangle.Center().X, Navigation.GetPosition().Top + rectangle.Center().Y); Navigation.Click(); Navigation.SystemRandomWait(Navigation.Speed.SelectNextInventoryItem); material.name = ScanMaterialName(section, out Bitmap nameplate); material.count = 0; // Check if new material has been found if (materials.Contains(material)) { goto LastPage; } else { if (!string.IsNullOrEmpty(material.name)) { // Scan Material Number material.count = ScanMaterialCount(rectangle, out Bitmap quantity); if (material.count == 0) { UserInterface.AddError($"Failed to parse quantity for {material.name}"); quantity.Save($"./logging/materials/{material.name}_Quantity.png"); } materials.Add(material); UserInterface.ResetCharacterDisplay(); UserInterface.SetMaterial(nameplate, quantity, material.name, material.count); previousMaterial.name = material.name; } } nameplate.Dispose(); Navigation.Wait(150); } Navigation.SetCursorPos(Navigation.GetPosition().Left + r.Last().Center().X, Navigation.GetPosition().Top + r.Last().Center().Y); Navigation.Click(); Navigation.Wait(150); // Scroll to next page for (int i = 0; i < rows - 1; i++) { scrollCount++; // scroll down for (int k = 0; k < 10; k++) { Navigation.sim.Mouse.VerticalScroll(-1); // skip a scroll if ((k == 7) && ((scrollCount % 3) == 0)) { k++; if (scrollCount % 9 == 0) { if (scrollCount == 18) { scrollCount = 0; } else { Navigation.sim.Mouse.VerticalScroll(-1); } } } Navigation.SystemRandomWait(Navigation.Speed.InventoryScroll); } } Navigation.SystemRandomWait(Navigation.Speed.Normal); ++page; } LastPage: // scroll down as much as possible for (int i = 0; i < 20; i++) { Navigation.sim.Mouse.VerticalScroll(-1); Navigation.SystemRandomWait(Navigation.Speed.InventoryScroll); } Navigation.Wait(500); (rectangles, _, _) = GetPageOfItems(section, page); bool passby = true; for (int i = rectangles.Count - 1; i >= 0; i--) // Click through but backwards to short-circuit after new materials { // Select Material Rectangle rectangle = rectangles[i]; Navigation.SetCursorPos(Navigation.GetPosition().Left + rectangle.Center().X, Navigation.GetPosition().Top + rectangle.Center().Y); Navigation.Click(); Navigation.SystemRandomWait(Navigation.Speed.SelectNextInventoryItem); material.name = ScanMaterialName(section, out Bitmap nameplate); material.count = 0; if (materials.Contains(material) && passby) { continue; } if (!materials.Contains(material)) { if (!string.IsNullOrEmpty(material.name)) { // Scan Material Number material.count = ScanMaterialCount(rectangle, out Bitmap quantity); if (material.count == 0) { UserInterface.AddError($"Failed to parse quantity for {material.name}"); quantity.Save($"./logging/materials/{material.name}_Quantity.png"); } materials.Add(material); UserInterface.ResetCharacterDisplay(); UserInterface.SetMaterial(nameplate, quantity, material.name, material.count); passby = false; // New material found so break on next old material quantity.Dispose(); } } else { nameplate.Dispose(); break; } Navigation.Wait(150); } }